{
  "openapi": "3.0.0",
  "paths": {
    "/": {
      "get": {
        "operationId": "AppController_getHomePage",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "App"
        ]
      }
    },
    "/swagger.json": {
      "get": {
        "operationId": "AppController_getSwaggerJson",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "App"
        ]
      }
    },
    "/login": {
      "get": {
        "operationId": "WebAuthController_getLoginPage",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "WebAuth"
        ]
      }
    },
    "/tools": {
      "get": {
        "operationId": "WebAuthController_getToolsPage",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "WebAuth"
        ]
      }
    },
    "/web-auth/login": {
      "post": {
        "operationId": "WebAuthController_login",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "WebAuth"
        ]
      }
    },
    "/web-auth/logout": {
      "get": {
        "operationId": "WebAuthController_logout",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "WebAuth"
        ]
      }
    },
    "/web-auth/data/licences": {
      "get": {
        "operationId": "WebAuthController_getLicences",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "WebAuth"
        ]
      }
    },
    "/web-auth/data/users": {
      "get": {
        "operationId": "WebAuthController_getUsers",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "WebAuth"
        ]
      }
    },
    "/web-auth/data/integrations/easydoct": {
      "get": {
        "operationId": "WebAuthController_getEasyDoctIntegrations",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "WebAuth"
        ]
      }
    },
    "/web-auth/data/integrations/testserveur": {
      "get": {
        "operationId": "WebAuthController_getTestServeurIntegrations",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "WebAuth"
        ]
      }
    },
    "/web-auth/data/kiosk": {
      "get": {
        "operationId": "WebAuthController_getKioskConfig",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "tags": [
          "WebAuth"
        ]
      }
    },
    "/licences": {
      "post": {
        "operationId": "LicenceController_create",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "example": "Licence Premium"
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Licence créée avec succès"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Créer une nouvelle licence",
        "tags": [
          "Licences"
        ]
      },
      "get": {
        "operationId": "LicenceController_findAll",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Liste des licences"
          },
          "403": {
            "description": "Accès interdit - SUPERADMIN requis"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Récupérer toutes les licences (SUPERADMIN uniquement)",
        "tags": [
          "Licences"
        ]
      }
    },
    "/licences/dashboard-summary": {
      "get": {
        "operationId": "LicenceController_dashboardSummary",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Récapitulatif par licence"
          },
          "403": {
            "description": "Accès interdit - SUPERADMIN requis"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Récapitulatif multi-licences pour le dashboard superadmin (saveur, état config persisté, compteurs)",
        "tags": [
          "Licences"
        ]
      }
    },
    "/licences/{id}": {
      "get": {
        "operationId": "LicenceController_findOne",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "ID de la licence",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Licence trouvée"
          },
          "404": {
            "description": "Licence introuvable"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Récupérer une licence par ID",
        "tags": [
          "Licences"
        ]
      },
      "put": {
        "operationId": "LicenceController_update",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "ID de la licence",
            "schema": {
              "type": "number"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "example": "Nouveau nom"
                  },
                  "activeIntegration": {
                    "type": "string",
                    "enum": [
                      "EASYDOCT",
                      "LIBRE",
                      "TEST_SERVEUR",
                      "NONE"
                    ],
                    "example": "EASYDOCT",
                    "description": "Intégration active (LIBRE = éditeur générique du Kiosk Integration Contract)"
                  },
                  "assignedFlavor": {
                    "type": "string",
                    "enum": [
                      "EASYDOCT",
                      "LIBRE"
                    ],
                    "nullable": true,
                    "example": "EASYDOCT",
                    "description": "Saveur imposée aux administrateurs (superadmin uniquement ; null = non assignée)"
                  },
                  "scanVaultEnabled": {
                    "type": "boolean",
                    "example": false,
                    "description": "Coffre documents : dépôt des ordonnances scannées (RDV direct) dans le bucket S3 privé du coffre (superadmin uniquement ; suppose une convention d'hébergement signée)"
                  },
                  "documentAnalysisEnabled": {
                    "type": "boolean",
                    "example": false,
                    "description": "Service d'analyse documentaire ApiBorne (analysis/, chiffré de bout en bout) : la borne y envoie les documents scannés au lieu du service local (superadmin uniquement ; données de santé, hébergement HDS)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Licence mise à jour"
          },
          "404": {
            "description": "Licence introuvable"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Mettre à jour une licence",
        "tags": [
          "Licences"
        ]
      },
      "delete": {
        "operationId": "LicenceController_remove",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "ID de la licence",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Licence supprimée"
          },
          "404": {
            "description": "Licence introuvable"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Supprimer une licence",
        "tags": [
          "Licences"
        ]
      }
    },
    "/auth/login": {
      "post": {
        "operationId": "AuthController_login",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "example": "user@example.com"
                  },
                  "password": {
                    "type": "string",
                    "example": "password123"
                  },
                  "rememberMe": {
                    "type": "boolean",
                    "example": true,
                    "description": "Pose le cookie httpOnly `apiborne_admin_refresh` (session persistante, AUTH_REMEMBER_DAYS jours)"
                  }
                },
                "required": [
                  "email",
                  "password"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Connexion réussie, token JWT retourné",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "access_token": {
                      "type": "string"
                    },
                    "user": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Email ou mot de passe invalide"
          }
        },
        "summary": "Se connecter et obtenir un token JWT",
        "tags": [
          "Authentication"
        ]
      }
    },
    "/auth/refresh": {
      "post": {
        "operationId": "AuthController_refresh",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Même forme que /auth/login (access_token, user, licence)"
          },
          "401": {
            "description": "Cookie absent, inconnu ou périmé"
          }
        },
        "summary": "Restaurer la session depuis le cookie « Se souvenir de moi » (nouveau JWT, rotation du cookie)",
        "tags": [
          "Authentication"
        ]
      }
    },
    "/auth/logout": {
      "post": {
        "operationId": "AuthController_logout",
        "parameters": [],
        "responses": {
          "200": {
            "description": "{ success: true }"
          }
        },
        "summary": "Se déconnecter : révoque le cookie de session persistante",
        "tags": [
          "Authentication"
        ]
      }
    },
    "/auth/profile": {
      "get": {
        "operationId": "AuthController_getProfile",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Profil récupéré avec succès"
          },
          "401": {
            "description": "Token manquant ou invalide"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Récupérer le profil de l'utilisateur connecté",
        "tags": [
          "Authentication"
        ]
      }
    },
    "/auth/accessibleLicences": {
      "get": {
        "operationId": "AuthController_accessibleLicences",
        "parameters": [],
        "responses": {
          "200": {
            "description": "{ licences: [{ id, name }] }"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Licences accessibles à l'utilisateur courant (superadmin : toutes ; login externe : celles accordées par l'éditeur)",
        "tags": [
          "Authentication"
        ]
      }
    },
    "/auth/switchLicence": {
      "post": {
        "description": "Génère un nouveau JWT avec la licence spécifiée. Superadmin : n'importe quelle licence ; admin : uniquement les licences accordées (login externe éditeur ou licence par défaut).",
        "operationId": "AuthController_switchLicence",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "licenceId": {
                    "type": "number",
                    "example": 1,
                    "description": "ID de la licence à utiliser"
                  }
                },
                "required": [
                  "licenceId"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Nouveau token JWT généré avec la licence spécifiée",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "access_token": {
                      "type": "string",
                      "description": "Nouveau JWT avec la licence switchée"
                    },
                    "currentLicenceId": {
                      "type": "number",
                      "description": "ID de la licence active"
                    },
                    "user": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Accès interdit - SUPERADMIN requis"
          },
          "404": {
            "description": "Licence introuvable"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Changer de licence temporairement (superadmin : tout ; admin : son périmètre)",
        "tags": [
          "Authentication"
        ]
      }
    },
    "/users": {
      "post": {
        "operationId": "UserController_create",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "example": "user@example.com"
                  },
                  "password": {
                    "type": "string",
                    "example": "password123"
                  },
                  "firstName": {
                    "type": "string",
                    "example": "John"
                  },
                  "lastName": {
                    "type": "string",
                    "example": "Doe"
                  },
                  "phone": {
                    "type": "string",
                    "example": "+33 6 12 34 56 78"
                  },
                  "role": {
                    "type": "string",
                    "enum": [
                      "user",
                      "superviseur",
                      "admin",
                      "superadmin"
                    ],
                    "example": "user"
                  },
                  "defaultLicenceId": {
                    "type": "number",
                    "example": 1
                  },
                  "canAccessCockpit": {
                    "type": "boolean",
                    "example": true
                  }
                },
                "required": [
                  "email",
                  "password",
                  "role"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Utilisateur créé avec succès"
          },
          "409": {
            "description": "Email déjà utilisé"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Créer un nouvel utilisateur",
        "tags": [
          "Users"
        ]
      },
      "get": {
        "operationId": "UserController_findAll",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Liste des utilisateurs"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Récupérer les utilisateurs (admin : ceux de sa licence)",
        "tags": [
          "Users"
        ]
      }
    },
    "/users/invite": {
      "post": {
        "operationId": "UserController_invite",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "example": "user@example.com"
                  },
                  "firstName": {
                    "type": "string",
                    "example": "John"
                  },
                  "lastName": {
                    "type": "string",
                    "example": "Doe"
                  },
                  "role": {
                    "type": "string",
                    "enum": [
                      "user",
                      "superviseur",
                      "admin",
                      "superadmin"
                    ],
                    "example": "user"
                  },
                  "defaultLicenceId": {
                    "type": "number",
                    "example": 1
                  }
                },
                "required": [
                  "email"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Invitation envoyée"
          },
          "409": {
            "description": "Email déjà utilisé"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Inviter un utilisateur par email (admin : sur sa licence uniquement)",
        "tags": [
          "Users"
        ]
      }
    },
    "/users/{id}/resend-invitation": {
      "post": {
        "operationId": "UserController_resendInvitation",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Invitation renvoyée"
          },
          "400": {
            "description": "Compte déjà activé ou email injoignable"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Renvoyer l'invitation d'un compte jamais activé (nouveau token, admin : sa licence uniquement)",
        "tags": [
          "Users"
        ]
      }
    },
    "/users/forgot-password": {
      "post": {
        "operationId": "UserController_forgotPassword",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string"
                  }
                },
                "required": [
                  "email"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Toujours success (ne révèle pas si le compte existe)"
          }
        },
        "summary": "Demander un email de réinitialisation de mot de passe",
        "tags": [
          "Users"
        ]
      }
    },
    "/users/set-password": {
      "post": {
        "operationId": "UserController_setPassword",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string"
                  },
                  "token": {
                    "type": "string"
                  },
                  "password": {
                    "type": "string"
                  }
                },
                "required": [
                  "email",
                  "token",
                  "password"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Mot de passe défini"
          },
          "400": {
            "description": "Invitation invalide ou expirée"
          }
        },
        "summary": "Définir le mot de passe depuis un lien d'invitation",
        "tags": [
          "Users"
        ]
      }
    },
    "/users/{id}": {
      "get": {
        "operationId": "UserController_findOne",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "ID de l'utilisateur",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Utilisateur trouvé"
          },
          "404": {
            "description": "Utilisateur introuvable"
          }
        },
        "summary": "Récupérer un utilisateur par ID",
        "tags": [
          "Users"
        ]
      },
      "put": {
        "operationId": "UserController_update",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "ID de l'utilisateur",
            "schema": {
              "type": "number"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string"
                  },
                  "password": {
                    "type": "string"
                  },
                  "firstName": {
                    "type": "string"
                  },
                  "lastName": {
                    "type": "string"
                  },
                  "phone": {
                    "type": "string"
                  },
                  "role": {
                    "type": "string",
                    "enum": [
                      "user",
                      "superviseur",
                      "admin",
                      "superadmin"
                    ]
                  },
                  "defaultLicenceId": {
                    "type": "number"
                  },
                  "canAccessCockpit": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Utilisateur mis à jour"
          },
          "404": {
            "description": "Utilisateur introuvable"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Mettre à jour un utilisateur",
        "tags": [
          "Users"
        ]
      },
      "delete": {
        "operationId": "UserController_remove",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "description": "ID de l'utilisateur",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Utilisateur supprimé"
          },
          "404": {
            "description": "Utilisateur introuvable"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Supprimer un utilisateur",
        "tags": [
          "Users"
        ]
      }
    },
    "/users/validate": {
      "post": {
        "operationId": "UserController_validate",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "example": "user@example.com"
                  },
                  "password": {
                    "type": "string",
                    "example": "password123"
                  }
                },
                "required": [
                  "email",
                  "password"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Credentials validés"
          }
        },
        "summary": "Valider les credentials d'un utilisateur",
        "tags": [
          "Users"
        ]
      }
    },
    "/licences/{licenceId}/integration/easydoct": {
      "post": {
        "operationId": "setIntegrationEasyDoct",
        "parameters": [
          {
            "name": "licenceId",
            "required": true,
            "in": "path",
            "description": "ID de la licence",
            "schema": {
              "type": "number"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "officeId": {
                    "type": "string",
                    "example": "office-123"
                  },
                  "officeVisibleId": {
                    "type": "string",
                    "example": "office-visible-456"
                  },
                  "targetUrl": {
                    "type": "string",
                    "example": "http://localhost/easydoct.com",
                    "description": "Fallback historique des deux base URLs (compat)"
                  },
                  "contractBaseUrl": {
                    "type": "string",
                    "nullable": true,
                    "description": "Base URL du contrat (apiborneIntegrationService/v1)"
                  },
                  "configServiceBaseUrl": {
                    "type": "string",
                    "nullable": true,
                    "description": "Base URL du config service EasyDoct legacy (apiborneConfigService) — vide = pas de forwards référentiels"
                  },
                  "supportedRoutes": {
                    "type": "object",
                    "nullable": true,
                    "description": "HISTORIQUE, ignoré — toutes les routes du contrat sont obligatoires (implémentation minimale acceptée). Toléré pour compat."
                  }
                },
                "required": []
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Intégration EasyDoct créée/mise à jour"
          },
          "404": {
            "description": "Licence introuvable"
          },
          "409": {
            "description": "La licence a déjà une autre intégration"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Créer ou mettre à jour l'intégration éditeur (contrat) d'une licence — EasyDoct ou tout éditeur implémentant le Kiosk Integration Contract",
        "tags": [
          "Integrations"
        ]
      },
      "delete": {
        "operationId": "removeIntegrationEasyDoct",
        "parameters": [
          {
            "name": "licenceId",
            "required": true,
            "in": "path",
            "description": "ID de la licence",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Intégration EasyDoct supprimée"
          },
          "404": {
            "description": "Licence ou intégration introuvable"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Supprimer l'intégration EasyDoct d'une licence",
        "tags": [
          "Integrations"
        ]
      }
    },
    "/licences/{licenceId}/integration/test-serveur": {
      "post": {
        "operationId": "setIntegrationTestServeur",
        "parameters": [
          {
            "name": "licenceId",
            "required": true,
            "in": "path",
            "description": "ID de la licence",
            "schema": {
              "type": "number"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "serverUrl": {
                    "type": "string",
                    "example": "https://test.example.com",
                    "nullable": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Intégration TestServeur créée/mise à jour"
          },
          "404": {
            "description": "Licence introuvable"
          },
          "409": {
            "description": "La licence a déjà une autre intégration"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Créer ou mettre à jour l'intégration TestServeur pour une licence",
        "tags": [
          "Integrations"
        ]
      },
      "delete": {
        "operationId": "removeIntegrationTestServeur",
        "parameters": [
          {
            "name": "licenceId",
            "required": true,
            "in": "path",
            "description": "ID de la licence",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Intégration TestServeur supprimée"
          },
          "404": {
            "description": "Licence ou intégration introuvable"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Supprimer l'intégration TestServeur d'une licence",
        "tags": [
          "Integrations"
        ]
      }
    },
    "/licences/{licenceId}/config-check": {
      "get": {
        "operationId": "getConfigCheck",
        "parameters": [
          {
            "name": "licenceId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "force",
            "required": false,
            "in": "query",
            "description": "true = re-sonder même si une validation est persistée (bouton Relancer)",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{ connectivity: {...}, integration: {...} }"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "État de la configuration de la licence : connectivité KioskReactor (définie + sondée) et intégration éditeur (endpoint contrat sondé) — pilote le verrouillage de l'admin",
        "tags": [
          "Integrations"
        ]
      }
    },
    "/licences/{licenceId}/contract-test": {
      "post": {
        "operationId": "runContractTest",
        "parameters": [
          {
            "name": "licenceId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "number"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "route"
                ],
                "properties": {
                  "route": {
                    "type": "string",
                    "description": "identifyPatients | getAppointmentByCode | getAppointmentById | listAppointmentDocuments | getNotificationReadiness | staffSignIn | getOfficePlaces | getExamTypes | getPractitioners | getRooms | getExams | getDocumentTypes"
                  },
                  "params": {
                    "type": "object",
                    "description": "Entrées utilisateur selon la route : criteria identify (lastName, firstName, birthDate, socialSecurityId), code, appointmentId, login/password, deviceId (optionnel)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Rapport { ok, status, durationMs, request, response, checks }"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Banc de test du contrat : exécute UN appel réel (lecture) vers l'éditeur avec les entrées fournies et rend un rapport détaillé (requête, statut, durée, réponse, checks de conformité)",
        "tags": [
          "Integrations"
        ]
      }
    },
    "/licences/{licenceId}/config-referentials": {
      "get": {
        "operationId": "getConfigReferentials",
        "parameters": [
          {
            "name": "licenceId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{ flavor, officePlaces, examTypes, practitioners, rooms, exams }"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Contenu des référentiels de l'éditeur (lieux, types d'examen, praticiens, salles, examens) tels que vus par le serveur ApiBorne — page « Référentiels éditeur » de l'admin",
        "tags": [
          "Integrations"
        ]
      }
    },
    "/api/contractRelay/{splat}": {
      "get": {
        "operationId": "ContractRelay_Relay",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "summary": "Relais générique des appels contrat de la borne vers l'éditeur (passthrough chiffré E2E)",
        "tags": [
          "ContractRelay"
        ]
      },
      "post": {
        "operationId": "ContractRelay_Relay",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "summary": "Relais générique des appels contrat de la borne vers l'éditeur (passthrough chiffré E2E)",
        "tags": [
          "ContractRelay"
        ]
      },
      "put": {
        "operationId": "ContractRelay_Relay",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "summary": "Relais générique des appels contrat de la borne vers l'éditeur (passthrough chiffré E2E)",
        "tags": [
          "ContractRelay"
        ]
      },
      "delete": {
        "operationId": "ContractRelay_Relay",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "summary": "Relais générique des appels contrat de la borne vers l'éditeur (passthrough chiffré E2E)",
        "tags": [
          "ContractRelay"
        ]
      },
      "patch": {
        "operationId": "ContractRelay_Relay",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "summary": "Relais générique des appels contrat de la borne vers l'éditeur (passthrough chiffré E2E)",
        "tags": [
          "ContractRelay"
        ]
      },
      "options": {
        "operationId": "ContractRelay_Relay",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "summary": "Relais générique des appels contrat de la borne vers l'éditeur (passthrough chiffré E2E)",
        "tags": [
          "ContractRelay"
        ]
      },
      "head": {
        "operationId": "ContractRelay_Relay",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "summary": "Relais générique des appels contrat de la borne vers l'éditeur (passthrough chiffré E2E)",
        "tags": [
          "ContractRelay"
        ]
      },
      "search": {
        "operationId": "ContractRelay_Relay",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "summary": "Relais générique des appels contrat de la borne vers l'éditeur (passthrough chiffré E2E)",
        "tags": [
          "ContractRelay"
        ]
      }
    },
    "/api/analysisRelay/{splat}": {
      "get": {
        "operationId": "AnalysisRelay_Relay",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "summary": "Relais des appels d'analyse documentaire de la borne vers le service HDS (passthrough chiffré, zero knowledge)",
        "tags": [
          "AnalysisRelay"
        ]
      },
      "post": {
        "operationId": "AnalysisRelay_Relay",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "summary": "Relais des appels d'analyse documentaire de la borne vers le service HDS (passthrough chiffré, zero knowledge)",
        "tags": [
          "AnalysisRelay"
        ]
      },
      "put": {
        "operationId": "AnalysisRelay_Relay",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "summary": "Relais des appels d'analyse documentaire de la borne vers le service HDS (passthrough chiffré, zero knowledge)",
        "tags": [
          "AnalysisRelay"
        ]
      },
      "delete": {
        "operationId": "AnalysisRelay_Relay",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "summary": "Relais des appels d'analyse documentaire de la borne vers le service HDS (passthrough chiffré, zero knowledge)",
        "tags": [
          "AnalysisRelay"
        ]
      },
      "patch": {
        "operationId": "AnalysisRelay_Relay",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "summary": "Relais des appels d'analyse documentaire de la borne vers le service HDS (passthrough chiffré, zero knowledge)",
        "tags": [
          "AnalysisRelay"
        ]
      },
      "options": {
        "operationId": "AnalysisRelay_Relay",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "summary": "Relais des appels d'analyse documentaire de la borne vers le service HDS (passthrough chiffré, zero knowledge)",
        "tags": [
          "AnalysisRelay"
        ]
      },
      "head": {
        "operationId": "AnalysisRelay_Relay",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "summary": "Relais des appels d'analyse documentaire de la borne vers le service HDS (passthrough chiffré, zero knowledge)",
        "tags": [
          "AnalysisRelay"
        ]
      },
      "search": {
        "operationId": "AnalysisRelay_Relay",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "summary": "Relais des appels d'analyse documentaire de la borne vers le service HDS (passthrough chiffré, zero knowledge)",
        "tags": [
          "AnalysisRelay"
        ]
      }
    },
    "/api/examReferential/{userSessionKey}": {
      "get": {
        "operationId": "getExamReferential",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "description": "JWT token utilisateur — mettre '-' pour s'authentifier par X-Licence-Uuid",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-licence-uuid",
            "required": true,
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Licence-Uuid",
            "in": "header",
            "description": "UUID de la licence — alternative au JWT (service d'analyse documentaire)",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{ licenceUuid, flavor, examTypes, exams }"
          },
          "401": {
            "description": "Authentification manquante ou invalide"
          }
        },
        "summary": "Examens et types d'examen de la licence (référentiel éditeur), pour le service d'analyse documentaire",
        "tags": [
          "Integrations"
        ]
      }
    },
    "/api/kioskReactorSetting/saveUpdateKioskReactorSetting": {
      "post": {
        "operationId": "saveUpdateKioskReactorSetting",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "userSessionKey": {
                    "type": "string",
                    "description": "JWT token"
                  },
                  "projectAuthorizationKey": {
                    "type": "string"
                  },
                  "brandId": {
                    "type": "string"
                  },
                  "brandAuthorizationKey": {
                    "type": "string"
                  },
                  "enableFeature": {
                    "type": "boolean"
                  },
                  "sesamReaderBaseHostUrl": {
                    "type": "string"
                  },
                  "useRetryOnApiFailure": {
                    "type": "boolean"
                  },
                  "retryOnApiFailureCount": {
                    "type": "integer"
                  },
                  "retryOnApiFailureStartHour": {
                    "type": "string"
                  },
                  "retryOnApiFailureEndHour": {
                    "type": "string"
                  },
                  "contractEncryptionPublicKey": {
                    "type": "string",
                    "nullable": true,
                    "description": "Clé publique RSA (PEM SPKI, >= 2048 bits) du chiffrement de bout en bout du contrat — vide/null = désactivé"
                  }
                },
                "required": [
                  "userSessionKey"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Configuration sauvegardÃ©e avec succÃ¨s",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "KioskReactorSetting": {
                      "type": "object"
                    },
                    "SessionKey": {
                      "type": "string"
                    },
                    "HasError": {
                      "type": "boolean",
                      "default": false
                    }
                  }
                }
              }
            }
          }
        },
        "summary": "Sauvegarder ou mettre Ã  jour la configuration KioskReactorSetting",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/getKioskReactorSetting/{userSessionKey}": {
      "get": {
        "operationId": "getKioskReactorSetting",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Configuration rÃ©cupÃ©rÃ©e avec succÃ¨s",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "KioskReactorSetting": {
                      "type": "object"
                    },
                    "SessionKey": {
                      "type": "string"
                    },
                    "HasError": {
                      "type": "boolean",
                      "default": false
                    }
                  }
                }
              }
            }
          }
        },
        "summary": "RÃ©cupÃ©rer la configuration KioskReactorSetting",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/kioskReactorSettingFeatures/getKioskReactorSettingFeatures/{userSessionKey}": {
      "get": {
        "operationId": "KioskReactorSetting_GetKioskReactorSettingFeatures",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Configuration récupérée"
          }
        },
        "summary": "Récupérer la configuration globale KioskReactorSettingFeatures",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/kioskReactorSettingFeatures/getKioskReactorSettingFeaturesByOfficePlaceId/{officePlaceId}/{userSessionKey}": {
      "get": {
        "operationId": "KioskReactorSetting_GetKioskReactorSettingFeaturesByOfficePlaceId",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "officePlaceId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Configuration par office place récupérée"
          }
        },
        "summary": "Récupérer la configuration KioskReactorSettingFeatures par office place",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/kioskReactorSettingFeatures/saveUpdateKioskReactorSettingFeatures": {
      "post": {
        "operationId": "KioskReactorSetting_SaveUpdateKioskReactorSettingFeatures",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Configuration sauvegardée"
          }
        },
        "summary": "Sauvegarder ou mettre à jour la config globale KioskReactorSettingFeatures",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/kioskReactorSettingFeatures/saveUpdateKioskReactorSettingFeaturesByOfficePlaceId": {
      "post": {
        "operationId": "KioskReactorSetting_SaveUpdateKioskReactorSettingFeaturesByOfficePlaceId",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Configuration par office place sauvegardée"
          }
        },
        "summary": "Sauvegarder ou mettre à jour la config par office place",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/kioskReactorSettingLanguages/getKioskReactorSettingLanguages/{userSessionKey}": {
      "get": {
        "operationId": "KioskReactorSetting_GetKioskReactorSettingLanguages",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Configuration récupérée"
          }
        },
        "summary": "Récupérer la configuration globale des langues de la borne",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/kioskReactorSettingLanguages/getKioskReactorSettingLanguagesByOfficePlaceId/{officePlaceId}/{userSessionKey}": {
      "get": {
        "operationId": "KioskReactorSetting_GetKioskReactorSettingLanguagesByOfficePlaceId",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "officePlaceId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Configuration par office place récupérée"
          }
        },
        "summary": "Récupérer la configuration des langues par office place",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/kioskReactorSettingLanguages/saveUpdateKioskReactorSettingLanguages": {
      "post": {
        "operationId": "KioskReactorSetting_SaveUpdateKioskReactorSettingLanguages",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Configuration sauvegardée"
          }
        },
        "summary": "Sauvegarder ou mettre à jour la config globale des langues",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/kioskReactorSettingLanguages/saveUpdateKioskReactorSettingLanguagesByOfficePlaceId": {
      "post": {
        "operationId": "KioskReactorSetting_SaveUpdateKioskReactorSettingLanguagesByOfficePlaceId",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Configuration par office place sauvegardée"
          }
        },
        "summary": "Sauvegarder ou mettre à jour la config des langues par office place",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/kioskReactorSettingMessages/getKioskReactorSettingMessages/{userSessionKey}": {
      "get": {
        "operationId": "KioskReactorSetting_GetKioskReactorSettingMessages",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Configuration rÃ©cupÃ©rÃ©e"
          }
        },
        "summary": "RÃ©cupÃ©rer la configuration KioskReactorSettingMessages",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/kioskReactorSettingMessages/getKioskReactorSettingMessagesPerPlace/{userSessionKey}": {
      "get": {
        "operationId": "KioskReactorSetting_GetKioskReactorSettingMessagesPerPlace",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Déclinaisons récupérées"
          }
        },
        "summary": "Lister les déclinaisons par lieu des messages (overrides du bloc global)",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/kioskReactorSettingMessages/saveUpdateKioskReactorSettingMessagesPerPlace": {
      "post": {
        "operationId": "KioskReactorSetting_SaveUpdateKioskReactorSettingMessagesPerPlace",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Déclinaison sauvegardée"
          }
        },
        "summary": "Sauvegarder la déclinaison par lieu des messages (upsert par officePlaceId)",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/kioskReactorSettingMessages/saveUpdateKioskReactorSettingMessages": {
      "post": {
        "operationId": "KioskReactorSetting_SaveUpdateKioskReactorSettingMessages",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Configuration sauvegardÃ©e"
          }
        },
        "summary": "Sauvegarder ou mettre Ã  jour KioskReactorSettingMessages",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/kioskReactorSettingPrinterCodes/getKioskReactorSettingPrinterCodes/{userSessionKey}": {
      "get": {
        "operationId": "KioskReactorSetting_GetKioskReactorSettingPrinterCodes",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Configuration rÃ©cupÃ©rÃ©e"
          }
        },
        "summary": "RÃ©cupÃ©rer la configuration KioskReactorSettingPrinterCodes",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/kioskReactorSettingPrinterCodes/saveUpdateKioskReactorSettingPrinterCodes": {
      "post": {
        "operationId": "KioskReactorSetting_SaveUpdateKioskReactorSettingPrinterCodes",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Configuration sauvegardÃ©e"
          }
        },
        "summary": "Sauvegarder ou mettre Ã  jour KioskReactorSettingPrinterCodes",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/kioskReactorSettingCheckinAppointmentDetail/getKioskReactorSettingCheckinAppointmentDetail/{userSessionKey}": {
      "get": {
        "operationId": "KioskReactorSetting_GetKioskReactorSettingCheckinAppointmentDetail",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Configuration récupérée"
          }
        },
        "summary": "Récupérer la configuration globale CheckinAppointmentDetail",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/kioskReactorSettingCheckinAppointmentDetail/getKioskReactorSettingCheckinAppointmentDetailByOfficePlaceId/{officePlaceId}/{userSessionKey}": {
      "get": {
        "operationId": "KioskReactorSetting_GetKioskReactorSettingCheckinAppointmentDetailByOfficePlaceId",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "officePlaceId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Configuration par office place récupérée"
          }
        },
        "summary": "Récupérer la configuration CheckinAppointmentDetail par office place",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/kioskReactorSettingCheckinAppointmentDetail/saveUpdateKioskReactorSettingCheckinAppointmentDetail": {
      "post": {
        "operationId": "KioskReactorSetting_SaveUpdateKioskReactorSettingCheckinAppointmentDetail",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Configuration sauvegardée"
          }
        },
        "summary": "Sauvegarder ou mettre à jour la config globale CheckinAppointmentDetail",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/kioskReactorSettingCheckinAppointmentDetail/saveUpdateKioskReactorSettingCheckinAppointmentDetailByOfficePlaceId": {
      "post": {
        "operationId": "KioskReactorSetting_SaveUpdateKioskReactorSettingCheckinAppointmentDetailByOfficePlaceId",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Configuration par office place sauvegardée"
          }
        },
        "summary": "Sauvegarder ou mettre à jour la config par office place",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/kioskReactorCheckInSystemNotifySetting/getKioskReactorCheckInSystemNotifySetting/{userSessionKey}": {
      "get": {
        "operationId": "KioskReactorSetting_GetKioskReactorCheckInSystemNotifySetting",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Configuration récupérée"
          }
        },
        "summary": "Récupérer la configuration globale KioskReactorCheckInSystemNotifySetting",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/kioskReactorCheckInSystemNotifySetting/getKioskReactorCheckInSystemNotifySettingByOfficePlaceId/{officePlaceId}/{userSessionKey}": {
      "get": {
        "operationId": "KioskReactorSetting_GetKioskReactorCheckInSystemNotifySettingByOfficePlaceId",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "officePlaceId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Configuration par office place récupérée"
          }
        },
        "summary": "Récupérer la configuration KioskReactorCheckInSystemNotifySetting par office place",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/kioskReactorCheckInSystemNotifySetting/saveUpdateKioskReactorCheckInSystemNotifySetting": {
      "post": {
        "operationId": "KioskReactorSetting_SaveUpdateKioskReactorCheckInSystemNotifySetting",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Configuration sauvegardée"
          }
        },
        "summary": "Sauvegarder ou mettre à jour la config globale KioskReactorCheckInSystemNotifySetting",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/kioskReactorCheckInSystemNotifySetting/saveUpdateKioskReactorCheckInSystemNotifySettingByOfficePlaceId": {
      "post": {
        "operationId": "KioskReactorSetting_SaveUpdateKioskReactorCheckInSystemNotifySettingByOfficePlaceId",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Configuration par office place sauvegardée"
          }
        },
        "summary": "Sauvegarder ou mettre à jour la config par office place",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/kioskReactorDirectAdmissionSetting/getKioskReactorDirectAdmissionSetting/{userSessionKey}": {
      "get": {
        "operationId": "KioskReactorSetting_GetKioskReactorDirectAdmissionSetting",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Configuration rÃ©cupÃ©rÃ©e"
          }
        },
        "summary": "RÃ©cupÃ©rer la configuration KioskReactorDirectAdmissionSetting",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/kioskReactorDirectAdmissionSetting/saveUpdateKioskReactorDirectAdmissionSetting": {
      "post": {
        "operationId": "KioskReactorSetting_SaveUpdateKioskReactorDirectAdmissionSetting",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Configuration sauvegardÃ©e"
          }
        },
        "summary": "Sauvegarder ou mettre Ã  jour KioskReactorDirectAdmissionSetting",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/kioskReactorSettingDisplay/getKioskReactorSettingDisplay/{userSessionKey}": {
      "get": {
        "operationId": "KioskReactorSetting_GetKioskReactorDisplaySetting",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Configuration rÃ©cupÃ©rÃ©e"
          }
        },
        "summary": "RÃ©cupÃ©rer la configuration KioskReactorSettingDisplay",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/kioskReactorSettingDisplay/saveUpdateKioskReactorSettingDisplay": {
      "post": {
        "operationId": "KioskReactorSetting_SaveUpdateKioskReactorDisplaySetting",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Configuration sauvegardÃ©e"
          }
        },
        "summary": "Sauvegarder ou mettre Ã  jour KioskReactorSettingDisplay",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/getKioskReactorSettingPatientLateAnomalies": {
      "post": {
        "operationId": "KioskReactorSetting_GetKioskReactorSettingPatientLateAnomalies",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Liste des anomalies récupérée"
          }
        },
        "summary": "Récupérer toutes les anomalies patient late",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/saveUpdateKioskReactorSettingPatientLateAnomaly": {
      "post": {
        "operationId": "KioskReactorSetting_SaveUpdateKioskReactorSettingPatientLateAnomaly",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Anomalie sauvegardée"
          }
        },
        "summary": "Sauvegarder ou mettre à jour une anomalie patient late",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/deleteKioskReactorSettingPatientLateAnomaly": {
      "post": {
        "operationId": "KioskReactorSetting_DeleteKioskReactorSettingPatientLateAnomaly",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Anomalie supprimée"
          }
        },
        "summary": "Supprimer une anomalie patient late",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/getKioskReactorSettingPatientAgeAnomalies": {
      "post": {
        "operationId": "KioskReactorSetting_GetKioskReactorSettingPatientAgeAnomalies",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Liste des anomalies récupérée"
          }
        },
        "summary": "Récupérer toutes les anomalies patient age",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/saveUpdateKioskReactorSettingPatientAgeAnomaly": {
      "post": {
        "operationId": "KioskReactorSetting_SaveUpdateKioskReactorSettingPatientAgeAnomaly",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Anomalie sauvegardée"
          }
        },
        "summary": "Sauvegarder ou mettre à jour une anomalie patient age",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/deleteKioskReactorSettingPatientAgeAnomaly": {
      "post": {
        "operationId": "KioskReactorSetting_DeleteKioskReactorSettingPatientAgeAnomaly",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Anomalie supprimée"
          }
        },
        "summary": "Supprimer une anomalie patient age",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSettingPatientInfoBookingOptions/getKioskReactorSettingPatientInfoBookingOptions/{userSessionKey}": {
      "get": {
        "operationId": "KioskReactorSettingPatientInfoBookingOptions_Get",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Configuration récupérée"
          }
        },
        "summary": "Récupérer la configuration PatientInfoBookingOptions",
        "tags": [
          "KioskReactorSettingPatientInfoBookingOptions"
        ]
      }
    },
    "/api/kioskReactorSettingPatientInfoBookingOptions/saveUpdateKioskReactorSettingPatientInfoBookingOptions": {
      "post": {
        "operationId": "KioskReactorSettingPatientInfoBookingOptions_SaveUpdate",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Configuration sauvegardée"
          }
        },
        "summary": "Sauvegarder ou mettre à jour PatientInfoBookingOptions",
        "tags": [
          "KioskReactorSettingPatientInfoBookingOptions"
        ]
      }
    },
    "/api/kioskReactorSetting/kioskReactorSettingRequiredDocumentSetting/getKioskReactorSettingRequiredDocumentSettings/{userSessionKey}": {
      "get": {
        "operationId": "KioskReactorSetting_GetKioskReactorSettingRequiredDocumentSettings",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Liste des paramètres de documents requis"
          }
        },
        "summary": "Récupérer les paramètres des documents requis (tous les types, avec overrides)",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/kioskReactorSettingRequiredDocumentSetting/getKioskReactorSettingRequiredDocumentSettingsByOfficePlaceId/{officePlaceId}/{userSessionKey}": {
      "get": {
        "operationId": "KioskReactorSetting_GetKioskReactorSettingRequiredDocumentSettingsByOfficePlaceId",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "officePlaceId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Liste des paramètres de documents requis du lieu"
          }
        },
        "summary": "Récupérer les paramètres des documents requis pour un lieu",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/kioskReactorSettingRequiredDocumentSetting/saveUpdateKioskReactorSettingRequiredDocumentSetting": {
      "post": {
        "operationId": "KioskReactorSetting_SaveUpdateKioskReactorSettingRequiredDocumentSetting",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Paramètre sauvegardé"
          }
        },
        "summary": "Sauvegarder ou réinitialiser l'override d'un document requis",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/kioskReactorSettingRequiredDocumentSetting/saveUpdateKioskReactorSettingRequiredDocumentSettingByOfficePlaceId": {
      "post": {
        "operationId": "KioskReactorSetting_SaveUpdateKioskReactorSettingRequiredDocumentSettingByOfficePlaceId",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Paramètre du lieu sauvegardé"
          }
        },
        "summary": "Sauvegarder ou réinitialiser l'override d'un document requis pour un lieu",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/kioskReactorSettingRequiredDocumentSetting/saveUpdateKioskReactorSettingRequiredDocumentOverrideGlobalConfig": {
      "post": {
        "operationId": "KioskReactorSetting_SaveUpdateKioskReactorSettingRequiredDocumentOverrideGlobalConfig",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Flag sauvegardé"
          }
        },
        "summary": "Activer/désactiver le remplacement de la config globale pour un lieu",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/kioskReactorSettingRequestMessage/getKioskReactorSettingRequestMessages/{userSessionKey}": {
      "get": {
        "operationId": "KioskReactorSetting_GetKioskReactorSettingRequestMessages",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{ KioskReactorSettingRequestMessages: [...] }"
          }
        },
        "summary": "Lister les messages de demande guichet (une entrée par lieu)",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/kioskReactorSettingRequestMessage/saveUpdateKioskReactorSettingRequestMessage": {
      "post": {
        "operationId": "KioskReactorSetting_SaveUpdateKioskReactorSettingRequestMessage",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Message sauvegardé"
          }
        },
        "summary": "Sauvegarder le message de demande guichet d'un lieu (upsert par officePlaceId)",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/kioskReactorSettingRequestMessage/getKioskReactorSettingWrongPlaceMessageDetails/{userSessionKey}": {
      "get": {
        "operationId": "KioskReactorSetting_GetKioskReactorSettingWrongPlaceMessageDetails",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{ KioskReactorSettingWrongPlaceMessageDetails: [...] }"
          }
        },
        "summary": "Lister les messages « mauvais lieu » (une entrée par lieu)",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/kioskReactorSettingRequestMessage/saveUpdateKioskReactorSettingWrongPlaceMessageDetail": {
      "post": {
        "operationId": "KioskReactorSetting_SaveUpdateKioskReactorSettingWrongPlaceMessageDetail",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Message sauvegardé"
          }
        },
        "summary": "Sauvegarder le message « mauvais lieu » d'un lieu (upsert par officePlaceId)",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/api/kioskReactorSetting/configImport/importLegacyConfig": {
      "post": {
        "operationId": "KioskReactorSetting_ImportLegacyConfig",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Rapport d'import par groupe de configuration"
          }
        },
        "summary": "Importer l'ancienne configuration kiosk depuis un serveur EasyDoct (legacy)",
        "tags": [
          "KioskReactorSetting"
        ]
      }
    },
    "/licences/{licenceId}/config-history": {
      "get": {
        "operationId": "listConfigHistory",
        "parameters": [
          {
            "name": "licenceId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Entrées d'historique (snapshots before/after inclus)"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Les 20 derniers changements de configuration de la licence (tous blocs confondus, plus récents d’abord)",
        "tags": [
          "ConfigHistory"
        ]
      }
    },
    "/licences/{licenceId}/config-history/{changeId}/revert": {
      "post": {
        "operationId": "revertConfigChange",
        "parameters": [
          {
            "name": "licenceId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "changeId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Changement annulé (entrée revert tracée)"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Annule un changement de configuration : réapplique le snapshot antérieur (bloc singleton) ou l'opération inverse (critère d'accueil)",
        "tags": [
          "ConfigHistory"
        ]
      }
    },
    "/api/kioskCheckInCriteria/getKioskCheckInCriterias/{userSessionKey}": {
      "get": {
        "operationId": "KioskCheckInCriteria_GetKioskCheckInCriterias",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "description": "JWT token utilisateur",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Liste des critères"
          },
          "401": {
            "description": "Token invalide"
          }
        },
        "summary": "Récupérer tous les critères de check-in kiosk",
        "tags": [
          "KioskCheckInCriteria"
        ]
      }
    },
    "/api/kioskCheckInCriteria/saveKioskCheckInCriteria": {
      "post": {
        "operationId": "KioskCheckInCriteria_SaveKioskCheckInCriteria",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "userSessionKey": {
                    "type": "string"
                  },
                  "question": {
                    "type": "string"
                  },
                  "imageUrl": {
                    "type": "string"
                  },
                  "enabled": {
                    "type": "boolean"
                  },
                  "blockingOnYes": {
                    "type": "boolean"
                  },
                  "examTypeIds": {
                    "type": "string"
                  },
                  "examIds": {
                    "type": "string"
                  },
                  "deviceIds": {
                    "type": "string"
                  },
                  "commonKioskAnomalyIds": {
                    "type": "string"
                  },
                  "matchAnomalyConditionsType": {
                    "type": "number"
                  },
                  "kioskAnomalyId": {
                    "type": "number"
                  }
                },
                "required": [
                  "userSessionKey",
                  "question"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Critère créé avec succès"
          },
          "401": {
            "description": "Token invalide"
          }
        },
        "summary": "Créer un nouveau critère de check-in kiosk",
        "tags": [
          "KioskCheckInCriteria"
        ]
      }
    },
    "/api/kioskCheckInCriteria/updateKioskCheckInCriteria": {
      "post": {
        "operationId": "KioskCheckInCriteria_UpdateKioskCheckInCriteria",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "userSessionKey": {
                    "type": "string"
                  },
                  "kioskCheckInCriteriaId": {
                    "type": "number"
                  },
                  "question": {
                    "type": "string"
                  },
                  "imageUrl": {
                    "type": "string"
                  },
                  "enabled": {
                    "type": "boolean"
                  },
                  "blockingOnYes": {
                    "type": "boolean"
                  },
                  "examTypeIds": {
                    "type": "string"
                  },
                  "examIds": {
                    "type": "string"
                  },
                  "deviceIds": {
                    "type": "string"
                  },
                  "commonKioskAnomalyIds": {
                    "type": "string"
                  },
                  "kioskAnomalyMatchCondition": {
                    "type": "number"
                  },
                  "kioskAnomalyId": {
                    "type": "number"
                  }
                },
                "required": [
                  "userSessionKey",
                  "kioskCheckInCriteriaId"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Critère mis à jour avec succès"
          },
          "401": {
            "description": "Token invalide"
          }
        },
        "summary": "Mettre à jour un critère de check-in kiosk",
        "tags": [
          "KioskCheckInCriteria"
        ]
      }
    },
    "/api/kioskCheckInCriteria/moveKioskCheckInCriteria/{userSessionKey}/{kioskCheckInCriteriaId}/{moveUp}": {
      "post": {
        "operationId": "KioskCheckInCriteria_MoveKioskCheckInCriteria",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "kioskCheckInCriteriaId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "moveUp",
            "required": true,
            "in": "path",
            "description": "true = monter, false = descendre",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Critère déplacé, liste réordonnée renvoyée"
          },
          "401": {
            "description": "Token invalide"
          }
        },
        "summary": "Déplacer un critère dans l'ordre d'affichage des questions",
        "tags": [
          "KioskCheckInCriteria"
        ]
      }
    },
    "/api/kioskCheckInCriteria/deleteKioskCheckInCriteria/{userSessionKey}/{kioskCheckInCriteriaId}": {
      "post": {
        "operationId": "KioskCheckInCriteria_DeleteKioskCheckInCriteria",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "kioskCheckInCriteriaId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Critère supprimé avec succès"
          },
          "401": {
            "description": "Token invalide"
          }
        },
        "summary": "Supprimer un critère de check-in kiosk",
        "tags": [
          "KioskCheckInCriteria"
        ]
      }
    },
    "/api/kioskAnomaly/saveUpdateKioskAnomaly": {
      "post": {
        "operationId": "KioskAnomalyController_saveUpdateKioskAnomaly",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "number",
                    "example": 1,
                    "description": "ID de l'anomalie (omis pour création, requis pour mise à jour)"
                  },
                  "name": {
                    "type": "string",
                    "example": "Anomalie test"
                  },
                  "description": {
                    "type": "string",
                    "example": "Description de l'anomalie"
                  },
                  "color": {
                    "type": "string",
                    "example": "#FF0000"
                  },
                  "code": {
                    "type": "string",
                    "example": "ANO001"
                  },
                  "keepForAppointment": {
                    "type": "boolean",
                    "example": false
                  },
                  "userSessionKey": {
                    "type": "string",
                    "description": "JWT token utilisateur (requis) - l'anomalie sera créée pour la licence de cet utilisateur"
                  }
                },
                "required": [
                  "name",
                  "userSessionKey"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Anomalie créée/mise à jour avec succès"
          },
          "401": {
            "description": "Token invalide"
          }
        },
        "summary": "Créer ou mettre à jour une anomalie kiosk",
        "tags": [
          "KioskAnomaly"
        ]
      }
    },
    "/api/kioskAnomaly/getKioskAnomalies/{userSessionKey}": {
      "get": {
        "operationId": "KioskAnomalyController_getKioskAnomalies",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "description": "JWT token utilisateur",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Liste des anomalies"
          },
          "401": {
            "description": "Token invalide"
          }
        },
        "summary": "Récupérer toutes les anomalies kiosk",
        "tags": [
          "KioskAnomaly"
        ]
      }
    },
    "/api/kioskAnomaly/deleteKioskAnomaly/{kioskAnomalyId}/{userSessionKey}": {
      "post": {
        "operationId": "KioskAnomalyController_deleteKioskAnomaly",
        "parameters": [
          {
            "name": "kioskAnomalyId",
            "required": true,
            "in": "path",
            "description": "ID de l'anomalie à supprimer",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "description": "JWT token utilisateur",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Anomalie supprimée avec succès"
          },
          "401": {
            "description": "Token invalide"
          },
          "404": {
            "description": "Anomalie introuvable"
          }
        },
        "summary": "Supprimer une anomalie kiosk",
        "tags": [
          "KioskAnomaly"
        ]
      }
    },
    "/global-anomalies": {
      "get": {
        "operationId": "listGlobalAnomalies",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Liste des anomalies globales (OfficeId 0)"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Lister les anomalies globales (superadmin)",
        "tags": [
          "KioskAnomaly"
        ]
      },
      "post": {
        "operationId": "saveGlobalAnomaly",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "Id": {
                    "type": "number",
                    "description": "Omis pour création"
                  },
                  "Name": {
                    "type": "string",
                    "example": "Échec accueil RIS"
                  },
                  "Description": {
                    "type": "string"
                  },
                  "Color": {
                    "type": "string",
                    "example": "#e07a5f",
                    "nullable": true
                  },
                  "Code": {
                    "type": "string",
                    "example": "ER"
                  },
                  "KeepForAppointment": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "Name",
                  "Code"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "L'anomalie globale enregistrée"
          },
          "400": {
            "description": "Name/Code manquant ou code déjà utilisé"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Créer ou mettre à jour une anomalie globale (superadmin)",
        "tags": [
          "KioskAnomaly"
        ]
      }
    },
    "/global-anomalies/{id}": {
      "delete": {
        "operationId": "deleteGlobalAnomaly",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Supprimée"
          },
          "404": {
            "description": "Anomalie globale introuvable"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Supprimer une anomalie globale (superadmin)",
        "tags": [
          "KioskAnomaly"
        ]
      }
    },
    "/api/kioskInformation/saveKioskInformation": {
      "post": {
        "operationId": "KioskInformation_SaveKioskInformation",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "userSessionKey": {
                    "type": "string",
                    "description": "JWT token utilisateur"
                  },
                  "name": {
                    "type": "string"
                  },
                  "information": {
                    "type": "string"
                  },
                  "imageUrl": {
                    "type": "string"
                  },
                  "enabled": {
                    "type": "boolean"
                  },
                  "examTypeIds": {
                    "type": "string"
                  },
                  "kioskInformationDisplayStep": {
                    "type": "number"
                  }
                },
                "required": [
                  "userSessionKey"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Information créée avec succès"
          },
          "401": {
            "description": "Token invalide"
          }
        },
        "summary": "Créer une nouvelle information kiosk",
        "tags": [
          "KioskInformation"
        ]
      }
    },
    "/api/kioskInformation/updateKioskInformation": {
      "post": {
        "operationId": "KioskInformation_UpdateKioskInformation",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "userSessionKey": {
                    "type": "string",
                    "description": "JWT token utilisateur"
                  },
                  "id": {
                    "type": "number",
                    "description": "ID de l'information à modifier"
                  },
                  "name": {
                    "type": "string"
                  },
                  "information": {
                    "type": "string"
                  },
                  "imageUrl": {
                    "type": "string"
                  },
                  "enabled": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "userSessionKey",
                  "id"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Information mise à jour avec succès"
          },
          "401": {
            "description": "Token invalide"
          },
          "404": {
            "description": "Information introuvable"
          }
        },
        "summary": "Mettre à jour une information kiosk existante",
        "tags": [
          "KioskInformation"
        ]
      }
    },
    "/api/kioskInformation/updateKioskInformationForReorder": {
      "post": {
        "operationId": "KioskInformation_UpdateKioskInformationForReorder",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "userSessionKey": {
                    "type": "string",
                    "description": "JWT token utilisateur"
                  },
                  "kioskInformationId": {
                    "type": "number",
                    "description": "ID de l'information à réordonner"
                  },
                  "targetKioskInformationGroupId": {
                    "type": "number",
                    "description": "ID du groupe cible (null = sans groupe)",
                    "nullable": true
                  },
                  "targetIndex": {
                    "type": "number",
                    "description": "Index cible dans la liste"
                  }
                },
                "required": [
                  "userSessionKey",
                  "kioskInformationId"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Ordre mis à jour avec succès"
          },
          "401": {
            "description": "Token invalide"
          },
          "404": {
            "description": "Information introuvable"
          }
        },
        "summary": "Mettre à jour l'ordre d'une information kiosk",
        "tags": [
          "KioskInformation"
        ]
      }
    },
    "/api/kioskInformation/getKioskInformations/{userSessionKey}": {
      "get": {
        "operationId": "KioskInformation_GetKioskInformations",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "description": "JWT token utilisateur",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Liste des informations"
          },
          "401": {
            "description": "Token invalide"
          }
        },
        "summary": "Récupérer toutes les informations kiosk",
        "tags": [
          "KioskInformation"
        ]
      }
    },
    "/api/kioskInformation/deleteKioskInformation/{userSessionKey}/{kioskInformationId}": {
      "post": {
        "operationId": "KioskInformation_DeleteKioskInformation",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "description": "JWT token utilisateur",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "kioskInformationId",
            "required": true,
            "in": "path",
            "description": "ID de l'information à supprimer",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Information supprimée avec succès"
          },
          "401": {
            "description": "Token invalide"
          },
          "404": {
            "description": "Information introuvable"
          }
        },
        "summary": "Supprimer une information kiosk",
        "tags": [
          "KioskInformation"
        ]
      }
    },
    "/api/kioskInformationGroup/saveUpdateKioskInformationGroup": {
      "post": {
        "operationId": "KioskInformationGroup_SaveUpdateKioskInformationGroup",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "userSessionKey": {
                    "type": "string",
                    "description": "JWT token utilisateur"
                  },
                  "Id": {
                    "type": "number",
                    "description": "ID du groupe (0 pour création)"
                  },
                  "name": {
                    "type": "string",
                    "description": "Nom du groupe (max 100 caractères)"
                  }
                },
                "required": [
                  "userSessionKey"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Groupe créé/mis à jour avec succès"
          },
          "401": {
            "description": "Token invalide"
          }
        },
        "summary": "Créer ou mettre à jour un groupe d'informations kiosk",
        "tags": [
          "KioskInformationGroup"
        ]
      }
    },
    "/api/kioskInformationGroup/getKioskInformationGroups/{userSessionKey}": {
      "get": {
        "operationId": "KioskInformationGroup_GetKioskInformationGroups",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "description": "JWT token utilisateur",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Liste des groupes d'informations"
          },
          "401": {
            "description": "Token invalide"
          }
        },
        "summary": "Récupérer tous les groupes d'informations kiosk",
        "tags": [
          "KioskInformationGroup"
        ]
      }
    },
    "/api/kioskInformationGroup/deleteKioskInformationGroup/{kioskInformationGroupId}/{userSessionKey}": {
      "post": {
        "operationId": "KioskInformationGroup_DeleteKioskInformationGroup",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "description": "JWT token utilisateur",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "kioskInformationGroupId",
            "required": true,
            "in": "path",
            "description": "ID du groupe à supprimer",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Groupe supprimé avec succès"
          },
          "401": {
            "description": "Token invalide"
          }
        },
        "summary": "Supprimer un groupe d'informations kiosk",
        "tags": [
          "KioskInformationGroup"
        ]
      }
    },
    "/api/kioskInformationGroup/moveKioskInformationGroup/{kioskInformationGroupId}/{moveLeft}": {
      "post": {
        "operationId": "KioskInformationGroup_MoveKioskInformationGroup",
        "parameters": [
          {
            "name": "kioskInformationGroupId",
            "required": true,
            "in": "path",
            "description": "ID du groupe à déplacer",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "moveLeft",
            "required": true,
            "in": "path",
            "description": "true pour déplacer vers la gauche, false vers la droite",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "userSessionKey",
            "required": true,
            "in": "query",
            "description": "JWT token utilisateur",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Groupe déplacé avec succès"
          },
          "401": {
            "description": "Token invalide"
          }
        },
        "summary": "Déplacer un groupe d'informations kiosk",
        "tags": [
          "KioskInformationGroup"
        ]
      }
    },
    "/api/kioskDeskRequestReason/getKioskDeskRequestReasons/{userSessionKey}": {
      "get": {
        "operationId": "KioskDeskRequestReasonController_getKioskDeskRequestReasons",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Liste des motifs"
          }
        },
        "summary": "Récupérer les motifs de demande guichet",
        "tags": [
          "KioskDeskRequestReason"
        ]
      }
    },
    "/api/kioskDeskRequestReason/saveKioskDeskRequestReason": {
      "post": {
        "operationId": "KioskDeskRequestReasonController_saveKioskDeskRequestReason",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Motif créé"
          }
        },
        "summary": "Créer un motif de demande guichet",
        "tags": [
          "KioskDeskRequestReason"
        ]
      }
    },
    "/api/kioskDeskRequestReason/updateKioskDeskRequestReason": {
      "post": {
        "operationId": "KioskDeskRequestReasonController_updateKioskDeskRequestReason",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Motif mis à jour"
          }
        },
        "summary": "Mettre à jour un motif de demande guichet",
        "tags": [
          "KioskDeskRequestReason"
        ]
      }
    },
    "/api/kioskDeskRequestReason/moveKioskDeskRequestReason/{kioskDeskRequestReasonId}/{moveLeft}": {
      "post": {
        "operationId": "KioskDeskRequestReasonController_moveKioskDeskRequestReason",
        "parameters": [
          {
            "name": "kioskDeskRequestReasonId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "moveLeft",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Motif déplacé"
          }
        },
        "summary": "Déplacer un motif de demande guichet dans l'ordre d'affichage",
        "tags": [
          "KioskDeskRequestReason"
        ]
      }
    },
    "/api/kioskDeskRequestReason/deleteKioskDeskRequestReason": {
      "post": {
        "operationId": "KioskDeskRequestReasonController_deleteKioskDeskRequestReason",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Motif supprimé"
          }
        },
        "summary": "Supprimer un motif de demande guichet",
        "tags": [
          "KioskDeskRequestReason"
        ]
      }
    },
    "/api/examType/getExamTypes/{userSessionKey}": {
      "get": {
        "operationId": "ExamTypeController_getExamTypes",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "description": "JWT token utilisateur",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Liste des types d'examens"
          }
        },
        "summary": "Récupérer les types d'examens depuis EasyDoct (préfixes de tickets locaux fusionnés)",
        "tags": [
          "ExamTypes"
        ]
      }
    },
    "/api/examType/updateKioskTicketPrefix": {
      "post": {
        "operationId": "ExamTypeController_updateKioskTicketPrefix",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "userSessionKey": {
                    "type": "string"
                  },
                  "examTypeId": {
                    "type": "number"
                  },
                  "prefix": {
                    "type": "string"
                  }
                },
                "required": [
                  "userSessionKey",
                  "examTypeId"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Préfixe mis à jour"
          }
        },
        "summary": "Mettre à jour le préfixe de ticket d'un type d'examen (stockage local)",
        "tags": [
          "ExamTypes"
        ]
      }
    },
    "/api/kioskBoard/getKioskBoards/{userSessionKey}": {
      "get": {
        "operationId": "KioskBoardController_getKioskBoards",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Liste des tableaux d'affichage"
          }
        },
        "summary": "Récupérer les tableaux d'affichage",
        "tags": [
          "KioskBoard"
        ]
      }
    },
    "/api/kioskBoard/getKioskBoardsInAllOffices/{userSessionKey}": {
      "get": {
        "operationId": "KioskBoardController_getKioskBoardsInAllOffices",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Liste des tableaux d'affichage"
          }
        },
        "summary": "Récupérer les tableaux d'affichage de tous les cabinets",
        "tags": [
          "KioskBoard"
        ]
      }
    },
    "/api/kioskBoard/saveKioskBoard": {
      "post": {
        "operationId": "KioskBoardController_saveKioskBoard",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Tableau d'affichage créé"
          }
        },
        "summary": "Créer un tableau d'affichage",
        "tags": [
          "KioskBoard"
        ]
      }
    },
    "/api/kioskBoard/updateKioskBoard": {
      "post": {
        "operationId": "KioskBoardController_updateKioskBoard",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Tableau d'affichage mis à jour"
          }
        },
        "summary": "Mettre à jour un tableau d'affichage",
        "tags": [
          "KioskBoard"
        ]
      }
    },
    "/api/kioskBoard/deleteKioskBoard": {
      "post": {
        "operationId": "KioskBoardController_deleteKioskBoard",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Tableau d'affichage supprimé"
          }
        },
        "summary": "Supprimer un tableau d'affichage",
        "tags": [
          "KioskBoard"
        ]
      }
    },
    "/api/kioskBoard/cleanKioskBoardEvents": {
      "post": {
        "operationId": "KioskBoardController_cleanKioskBoardEvents",
        "parameters": [],
        "responses": {
          "200": {
            "description": "{ Deleted, Detached }"
          }
        },
        "summary": "Nettoyer un tableau d'affichage : supprime ses events d'affichage KioskReactor (iso « Clean board » de totemSystemWeb)",
        "tags": [
          "KioskBoard"
        ]
      }
    },
    "/api/kioskBoard/getCallToKioskDeskKioskBoards/{userSessionKey}": {
      "get": {
        "operationId": "KioskBoardController_getCallToKioskDeskKioskBoards",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Liste des tableaux d'appel"
          }
        },
        "summary": "Récupérer les tableaux d'appel au bureau",
        "tags": [
          "KioskBoard"
        ]
      }
    },
    "/api/kioskBoard/getCallToKioskDeskKioskBoardsInAllOffices/{userSessionKey}": {
      "get": {
        "operationId": "KioskBoardController_getCallToKioskDeskKioskBoardsInAllOffices",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Liste des tableaux d'appel"
          }
        },
        "summary": "Récupérer les tableaux d'appel de tous les cabinets",
        "tags": [
          "KioskBoard"
        ]
      }
    },
    "/api/kioskBoard/getCallToKioskDeskKioskBoardCurrentUser/{userSessionKey}": {
      "get": {
        "operationId": "KioskBoardController_getCallToKioskDeskKioskBoardCurrentUser",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tableau d'appel de l'utilisateur"
          }
        },
        "summary": "Récupérer le tableau d'appel de l'utilisateur courant",
        "tags": [
          "KioskBoard"
        ]
      }
    },
    "/api/kioskBoard/createCallToKioskDeskKioskBoard": {
      "post": {
        "operationId": "KioskBoardController_createCallToKioskDeskKioskBoard",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Tableau d'appel créé"
          }
        },
        "summary": "Créer un tableau d'appel au bureau",
        "tags": [
          "KioskBoard"
        ]
      }
    },
    "/api/kioskBoard/updateCallToKioskDeskKioskBoard": {
      "post": {
        "operationId": "KioskBoardController_updateCallToKioskDeskKioskBoard",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Tableau d'appel mis à jour"
          }
        },
        "summary": "Mettre à jour un tableau d'appel au bureau",
        "tags": [
          "KioskBoard"
        ]
      }
    },
    "/api/kioskBoard/deleteCallToKioskDeskKioskBoard": {
      "post": {
        "operationId": "KioskBoardController_deleteCallToKioskDeskKioskBoard",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Tableau d'appel supprimé"
          }
        },
        "summary": "Supprimer un tableau d'appel au bureau",
        "tags": [
          "KioskBoard"
        ]
      }
    },
    "/kiosk-reactor/brands": {
      "get": {
        "operationId": "listKioskReactorBrands",
        "parameters": [],
        "responses": {
          "200": {
            "description": "[{ brandId, brandName, contactEmail }]"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Lister les companies (brands) KioskReactor par nom — sans les clés",
        "tags": [
          "KioskReactor"
        ]
      },
      "post": {
        "operationId": "createKioskReactorBrand",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "brandName"
                ],
                "properties": {
                  "brandName": {
                    "type": "string",
                    "description": "Nom de la company"
                  },
                  "contactEmail": {
                    "type": "string",
                    "nullable": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Credentials de la company créée"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Créer une NOUVELLE company KioskReactor (brand + projet « ApiBorne » par défaut, clés UUID) — n'affecte aucun document existant",
        "tags": [
          "KioskReactor"
        ]
      }
    },
    "/kiosk-reactor/brands/{brandId}": {
      "get": {
        "operationId": "getKioskReactorBrand",
        "parameters": [
          {
            "name": "brandId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{ brandId, brandName, brandAuthorizationKey, projects: [{ id, name, authKey }] }"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Credentials d'une company (clé de marque + projets)",
        "tags": [
          "KioskReactor"
        ]
      }
    },
    "/kiosk-reactor/brands/{brandId}/devices": {
      "post": {
        "operationId": "createKioskReactorDevice",
        "parameters": [
          {
            "name": "brandId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Nom de la borne (unique dans la company)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "{ deviceId, name, brandId, projectId, projectName, projectCreated }"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Créer une NOUVELLE borne (device) dans la company — id généré, défauts usbDevice/lite + imprimante EPSON, nom unique dans la company ; le projet « ApiBorne » est créé au besoin",
        "tags": [
          "KioskReactor"
        ]
      }
    },
    "/kiosk-reactor/brands/{brandId}/boards": {
      "post": {
        "operationId": "createKioskReactorBoard",
        "parameters": [
          {
            "name": "brandId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name",
                  "kind"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Nom du tableau (unique dans la company)"
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "kioskDesk",
                      "callToDesk"
                    ],
                    "description": "kioskDesk = tableau d'affichage salle d'attente ; callToDesk = tableau d'appel guichet"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "{ boardId, name, brandId, kind }"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Créer un NOUVEAU tableau (board) dans la company en clonant le modèle du type demandé — configuration complète reprise, nom unique dans la company",
        "tags": [
          "KioskReactor"
        ]
      }
    },
    "/kiosk-reactor/brands/{brandId}/devices/{deviceId}": {
      "get": {
        "operationId": "getKioskReactorDevice",
        "parameters": [
          {
            "name": "brandId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "deviceId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Détail éditable d'une borne de la company (champs whitelistés)",
        "tags": [
          "KioskReactor"
        ]
      },
      "patch": {
        "operationId": "updateKioskReactorDevice",
        "parameters": [
          {
            "name": "brandId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "deviceId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Champs éditables à modifier"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": ""
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Mise à jour WHITELISTÉE d'une borne de la company (nom, toggles, imprimante, écran…) — brandId/projectId/Stripe intouchables",
        "tags": [
          "KioskReactor"
        ]
      }
    },
    "/kiosk-reactor/brands/{brandId}/boards/{boardId}": {
      "get": {
        "operationId": "getKioskReactorBoard",
        "parameters": [
          {
            "name": "brandId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "boardId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Détail éditable d'un tableau de la company (champs whitelistés)",
        "tags": [
          "KioskReactor"
        ]
      },
      "patch": {
        "operationId": "updateKioskReactorBoard",
        "parameters": [
          {
            "name": "brandId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "boardId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Champs éditables à modifier"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": ""
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Mise à jour WHITELISTÉE d'un tableau de la company (nom, logo, header, colonnes, css, delays…)",
        "tags": [
          "KioskReactor"
        ]
      }
    },
    "/kiosk-reactor/fleet": {
      "get": {
        "operationId": "listKioskReactorFleet",
        "parameters": [],
        "responses": {
          "200": {
            "description": "[{ brandId, brandName, contactEmail, deviceCount, licences: [{ id, name }] }]"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Parc KioskReactor : companies triées par nom, avec leur nombre de bornes et les licences ApiBorne rattachées (plusieurs possibles)",
        "tags": [
          "KioskReactor"
        ]
      }
    },
    "/kiosk-reactor/fleet/{brandId}": {
      "get": {
        "operationId": "getKioskReactorFleetBrand",
        "parameters": [
          {
            "name": "brandId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{ brandId, brandName, brandAuthorizationKey, projects: [{ id, name, authKey }], devices: [{ deviceId, name, …, apiborne }] }"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Détail parc d'une company : clés, projets et bornes (champs whitelistés — aucune config Stripe) avec leur rattachement ApiBorne",
        "tags": [
          "KioskReactor"
        ]
      }
    },
    "/api/kioskDesk/getKioskDesks/{userSessionKey}": {
      "get": {
        "operationId": "KioskDeskController_getKioskDesks",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Liste des guichets"
          }
        },
        "summary": "Récupérer les guichets",
        "tags": [
          "KioskDesk"
        ]
      }
    },
    "/api/kioskDesk/getRemainingKioskDesks/{userSessionKey}": {
      "get": {
        "operationId": "KioskDeskController_getRemainingKioskDesks",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Liste des guichets restants"
          }
        },
        "summary": "Récupérer les guichets restants",
        "tags": [
          "KioskDesk"
        ]
      }
    },
    "/api/kioskDesk/getKioskDesksWithAssociatedUsers/{userSessionKey}": {
      "get": {
        "operationId": "KioskDeskController_getKioskDesksWithAssociatedUsers",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Liste des guichets avec utilisateurs"
          }
        },
        "summary": "Récupérer les guichets avec utilisateurs associés",
        "tags": [
          "KioskDesk"
        ]
      }
    },
    "/api/kioskDesk/saveKioskDesk": {
      "post": {
        "operationId": "KioskDeskController_saveKioskDesk",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Guichet créé"
          }
        },
        "summary": "Créer un guichet",
        "tags": [
          "KioskDesk"
        ]
      }
    },
    "/api/kioskDesk/updateKioskDesk": {
      "post": {
        "operationId": "KioskDeskController_updateKioskDesk",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Guichet mis à jour"
          }
        },
        "summary": "Mettre à jour un guichet",
        "tags": [
          "KioskDesk"
        ]
      }
    },
    "/api/kioskDesk/deleteKioskDesk": {
      "post": {
        "operationId": "KioskDeskController_deleteKioskDesk",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Guichet supprimé"
          }
        },
        "summary": "Supprimer un guichet",
        "tags": [
          "KioskDesk"
        ]
      }
    },
    "/api/user/getUsersDetail/{token}": {
      "get": {
        "operationId": "KioskDeskUserForwardController_getUsersDetail",
        "parameters": [
          {
            "name": "token",
            "required": true,
            "in": "path",
            "description": "JWT token utilisateur",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{ officeUsersDetail: [...] }"
          },
          "401": {
            "description": "Token invalide ou expiré"
          }
        },
        "summary": "Utilisateurs du cabinet (EasyDoct forwardé ; liste vide en saveur libre)",
        "tags": [
          "User"
        ]
      }
    },
    "/api/exam/getExams/{token}": {
      "get": {
        "operationId": "ExamController_getExamsByToken",
        "parameters": [
          {
            "name": "token",
            "required": true,
            "in": "path",
            "description": "JWT token utilisateur",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Liste des examens"
          },
          "401": {
            "description": "Token invalide ou expiré"
          }
        },
        "summary": "Examens (EasyDoct forwardé ; route config du contrat en saveur libre)",
        "tags": [
          "Exams"
        ]
      }
    },
    "/api/officePlace/getOfficePlaces/{token}/{examTypeId}/{examId}/{filterNoRooms}": {
      "get": {
        "operationId": "OfficePlaceController_getOfficePlaces",
        "parameters": [
          {
            "name": "token",
            "required": true,
            "in": "path",
            "description": "JWT token utilisateur",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "examTypeId",
            "required": true,
            "in": "path",
            "description": "ID du type d'examen (0 si non applicable)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "examId",
            "required": true,
            "in": "path",
            "description": "ID de l'examen (0 si non applicable)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "filterNoRooms",
            "required": true,
            "in": "path",
            "description": "Filtre pour exclure les salles (true/false)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{ xOfficePlaces: [{ id, name }] }"
          },
          "401": {
            "description": "Token invalide ou expiré"
          }
        },
        "summary": "Lieux de consultation (EasyDoct forwardé, ou route config du contrat en saveur libre)",
        "tags": [
          "OfficePlaces"
        ]
      }
    },
    "/api/kioskDevice/hasDeviceForOfficePlace": {
      "post": {
        "operationId": "KioskDeviceController_hasDeviceForOfficePlace",
        "parameters": [
          {
            "name": "authorization",
            "required": true,
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "description": "brandAuthorizationKey de la licence (KioskReactorSetting)",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "officePlaceId"
                ],
                "properties": {
                  "officePlaceId": {
                    "type": "number",
                    "description": "Id du lieu de la SALLE du RDV (pas celui de la borne)"
                  },
                  "officeVisibleId": {
                    "type": "string",
                    "nullable": true,
                    "description": "Uuid de l'office éditeur appelant — identifiant de référence"
                  },
                  "licenceUuid": {
                    "type": "string",
                    "nullable": true,
                    "description": "Prime sur les autres"
                  },
                  "brandId": {
                    "type": "string",
                    "nullable": true,
                    "description": "Requis sans officeVisibleId/licenceUuid"
                  },
                  "officeId": {
                    "type": "string",
                    "nullable": true,
                    "description": "Repli legacy"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "{ exists: boolean } — `false` = licence résolue mais AUCUNE borne sur ce lieu (réponse concluante)"
          },
          "401": {
            "description": "Clé de marque invalide (contrôle indisponible)"
          }
        },
        "summary": "Existe-t-il une borne de la licence couvrant ce lieu ? (lu par EasyDoct quand UseExternalConfiguration est actif — son garde d'émission de ticket ne voit pas les bornes déclarées uniquement côté ApiBorne)",
        "tags": [
          "KioskDevice"
        ]
      }
    },
    "/api/kioskDevice/saveKioskDevice": {
      "post": {
        "operationId": "KioskDeviceController_saveKioskDevice",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "externalId": {
                    "type": "string",
                    "example": "KIOSK-001",
                    "description": "Identifiant externe unique du device"
                  },
                  "deviceName": {
                    "type": "string",
                    "example": "Kiosk Reception",
                    "description": "Nom du device"
                  },
                  "officePlaceIds": {
                    "type": "array",
                    "items": {
                      "type": "number"
                    },
                    "example": [
                      1,
                      2,
                      3
                    ],
                    "description": "IDs des lieux de consultation"
                  },
                  "defaultTicketPrinter": {
                    "type": "boolean",
                    "example": false
                  },
                  "officePrinterIp": {
                    "type": "string",
                    "example": "192.168.1.100"
                  },
                  "userSessionKey": {
                    "type": "string",
                    "description": "JWT token utilisateur (requis) - le device sera créé pour la licence de cet utilisateur"
                  }
                },
                "required": [
                  "externalId",
                  "userSessionKey"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Device créé avec succès"
          },
          "401": {
            "description": "Token invalide"
          },
          "409": {
            "description": "ExternalId déjà existant"
          }
        },
        "summary": "Créer un nouveau device kiosk",
        "tags": [
          "KioskDevice"
        ]
      }
    },
    "/api/kioskDevice/updateKioskDevice": {
      "post": {
        "operationId": "KioskDeviceController_updateKioskDevice",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "number",
                    "example": 1,
                    "description": "ID du device à mettre à jour"
                  },
                  "externalId": {
                    "type": "string",
                    "example": "KIOSK-001"
                  },
                  "deviceName": {
                    "type": "string",
                    "example": "Kiosk Reception Updated"
                  },
                  "officePlaceIds": {
                    "type": "array",
                    "items": {
                      "type": "number"
                    },
                    "example": [
                      1,
                      2,
                      3
                    ]
                  },
                  "defaultTicketPrinter": {
                    "type": "boolean",
                    "example": true
                  },
                  "userSessionKey": {
                    "type": "string",
                    "description": "JWT token utilisateur (requis)"
                  }
                },
                "required": [
                  "id",
                  "userSessionKey"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Device mis à jour avec succès"
          },
          "401": {
            "description": "Token invalide"
          },
          "404": {
            "description": "Device introuvable"
          }
        },
        "summary": "Mettre à jour un device kiosk",
        "tags": [
          "KioskDevice"
        ]
      }
    },
    "/api/kioskDevice/deleteKioskDevice": {
      "post": {
        "operationId": "KioskDeviceController_deleteKioskDevice",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "number",
                    "example": 1,
                    "description": "ID du device à supprimer"
                  },
                  "userSessionKey": {
                    "type": "string",
                    "description": "JWT token utilisateur (requis)"
                  }
                },
                "required": [
                  "id",
                  "userSessionKey"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Device supprimé avec succès"
          },
          "401": {
            "description": "Token invalide"
          },
          "404": {
            "description": "Device introuvable"
          }
        },
        "summary": "Supprimer un device kiosk",
        "tags": [
          "KioskDevice"
        ]
      }
    },
    "/api/kioskDevice/kioskDeviceCommand/{command}": {
      "post": {
        "description": "Relaie la commande au cloud KioskReactor avec la clé de la licence (jamais exposée au client). Un 200 signifie que la commande a été DÉPOSÉE dans la file du device : la borne la dépile ensuite, donc l’exécution effective n’est pas garantie par cette réponse.",
        "operationId": "KioskDeviceController_kioskDeviceCommand",
        "parameters": [
          {
            "name": "command",
            "required": true,
            "in": "path",
            "description": "Commande à envoyer",
            "schema": {
              "enum": [
                "reboot",
                "reloadHomePage",
                "startRdp",
                "stopRdp"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "deviceId": {
                    "type": "number",
                    "example": 1,
                    "description": "Id APIBORNE de la borne"
                  },
                  "userSessionKey": {
                    "type": "string",
                    "description": "JWT token utilisateur (requis)"
                  },
                  "source": {
                    "type": "string",
                    "enum": [
                      "cockpit",
                      "cockpit-extension",
                      "admin",
                      "mcp"
                    ],
                    "description": "Canal déclencheur, tracé dans l’événement Elastic « action distante » avec l’auteur (lu dans le JWT). Optionnel : absent = « unknown »"
                  }
                },
                "required": [
                  "deviceId",
                  "userSessionKey"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Commande déposée auprès de KioskReactor"
          },
          "400": {
            "description": "Commande inconnue, borne sans ExternalId, clé absente ou refusée"
          },
          "401": {
            "description": "Token invalide"
          },
          "404": {
            "description": "Device introuvable"
          }
        },
        "summary": "Envoyer une commande à une borne (reboot, reloadHomePage, startRdp, stopRdp)",
        "tags": [
          "KioskDevice"
        ]
      }
    },
    "/api/kioskDevice/getKioskDevices/{userSessionKey}": {
      "get": {
        "operationId": "KioskDeviceController_getKioskDevices",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "description": "JWT token utilisateur",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Liste des devices"
          },
          "401": {
            "description": "Token invalide"
          }
        },
        "summary": "Récupérer tous les devices kiosk pour la licence de l'utilisateur",
        "tags": [
          "KioskDevice"
        ]
      }
    },
    "/api/kioskDevice/getKioskDevicesInAllOffices/{userSessionKey}": {
      "get": {
        "operationId": "KioskDeviceController_getKioskDevicesInAllOffices",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "description": "JWT token utilisateur",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Liste de tous les devices"
          },
          "401": {
            "description": "Token invalide"
          }
        },
        "summary": "Récupérer tous les devices kiosk de toutes les licences",
        "tags": [
          "KioskDevice"
        ]
      }
    },
    "/api/kioskDevice/getKioskDeviceByExternalId/{externalId}": {
      "get": {
        "operationId": "KioskDeviceController_getKioskDeviceByExternalId",
        "parameters": [
          {
            "name": "externalId",
            "required": true,
            "in": "path",
            "description": "ExternalId du device",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Device trouvé (kioskDeviceInfo = device + kioskConfig format EasyDoct + kioskAnomalies)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GetKioskDeviceByExternalIdResultDto"
                }
              }
            }
          },
          "404": {
            "description": "Device introuvable"
          }
        },
        "summary": "Récupérer un device kiosk par son ExternalId",
        "tags": [
          "KioskDevice"
        ]
      }
    },
    "/api/kioskDevice/keepAlive/{externalId}": {
      "post": {
        "operationId": "kioskDeviceKeepAlive",
        "parameters": [
          {
            "name": "externalId",
            "required": true,
            "in": "path",
            "description": "ExternalId de la borne",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{ ok: true }"
          },
          "404": {
            "description": "Device introuvable"
          }
        },
        "summary": "Signe de vie de la page de la borne (statut admin)",
        "tags": [
          "KioskDevice"
        ]
      }
    },
    "/api/kioskTheme/saveUpdateKioskTheme": {
      "post": {
        "operationId": "KioskThemeController_saveUpdateKioskTheme",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "number",
                    "example": 1,
                    "description": "ID du thème (omis pour création, requis pour mise à jour)"
                  },
                  "name": {
                    "type": "string",
                    "example": "Theme Modern",
                    "description": "Nom du thème"
                  },
                  "base64JsonStyle": {
                    "type": "string",
                    "example": "eyJjb2xvcnMiOnsicHJpbWFyeSI6IiMwMDdiZmYifX0=",
                    "description": "Style JSON encodé en base64"
                  },
                  "externalId": {
                    "type": "string",
                    "example": "THEME-001"
                  },
                  "visibleId": {
                    "type": "string",
                    "example": "T001"
                  },
                  "creationUser": {
                    "type": "string",
                    "example": "admin@example.com"
                  },
                  "lastModificationUser": {
                    "type": "string",
                    "example": "admin@example.com"
                  },
                  "userSessionKey": {
                    "type": "string",
                    "description": "JWT token utilisateur (requis)"
                  }
                },
                "required": [
                  "name",
                  "userSessionKey"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Thème créé/mis à jour avec succès"
          },
          "401": {
            "description": "Token invalide"
          }
        },
        "summary": "Créer ou mettre à jour un thème kiosk",
        "tags": [
          "KioskTheme"
        ]
      }
    },
    "/api/kioskTheme/getKioskThemes/{userSessionKey}": {
      "get": {
        "operationId": "KioskThemeController_getKioskThemes",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "description": "JWT token utilisateur",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Liste des thèmes complets"
          },
          "401": {
            "description": "Token invalide"
          }
        },
        "summary": "Récupérer tous les thèmes kiosk complets",
        "tags": [
          "KioskTheme"
        ]
      }
    },
    "/api/kioskTheme/getLightKioskThemes/{userSessionKey}": {
      "get": {
        "operationId": "KioskThemeController_getLightKioskThemes",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "description": "JWT token utilisateur",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Liste des thèmes légers"
          },
          "401": {
            "description": "Token invalide"
          }
        },
        "summary": "Récupérer tous les thèmes kiosk légers (sans Base64JsonStyle)",
        "tags": [
          "KioskTheme"
        ]
      }
    },
    "/api/kioskTheme/convertKioskThemeToTokens": {
      "post": {
        "operationId": "KioskThemeController_convertKioskThemeToTokens",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "number",
                    "example": 1,
                    "description": "ID du thème legacy à convertir"
                  },
                  "apply": {
                    "type": "boolean",
                    "example": false,
                    "description": "false/omis = aperçu (tokens proposés + unmappedKeys + droppedValues) ; true = écrit les tokens, supprime le blob et propage aux bornes"
                  },
                  "userSessionKey": {
                    "type": "string",
                    "description": "JWT token utilisateur (requis)"
                  }
                },
                "required": [
                  "id",
                  "userSessionKey"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Rapport de conversion (et thème converti si apply)"
          },
          "400": {
            "description": "Thème déjà en tokens ou sans style"
          },
          "401": {
            "description": "Token invalide"
          },
          "404": {
            "description": "Thème introuvable"
          }
        },
        "summary": "Convertir un thème legacy (blob MUI base64) vers le format tokens v2 — apply: false = rapport seul",
        "tags": [
          "KioskTheme"
        ]
      }
    },
    "/api/kioskTheme/deleteKioskTheme": {
      "post": {
        "operationId": "KioskThemeController_deleteKioskTheme",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "number",
                    "example": 1,
                    "description": "ID du thème à supprimer"
                  },
                  "userSessionKey": {
                    "type": "string",
                    "description": "JWT token utilisateur (requis)"
                  }
                },
                "required": [
                  "id",
                  "userSessionKey"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Thème supprimé avec succès"
          },
          "401": {
            "description": "Token invalide"
          },
          "404": {
            "description": "Thème introuvable"
          }
        },
        "summary": "Supprimer un thème kiosk",
        "tags": [
          "KioskTheme"
        ]
      }
    },
    "/api/practitioner/getPractitionerResources/{token}": {
      "get": {
        "operationId": "PractitionerController_getPractitionerResources",
        "parameters": [
          {
            "name": "token",
            "required": true,
            "in": "path",
            "description": "JWT token utilisateur",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Liste des ressources praticiens"
          },
          "401": {
            "description": "Token invalide ou expiré"
          }
        },
        "summary": "Praticiens (EasyDoct forwardé ; route config du contrat en saveur libre)",
        "tags": [
          "Practitioner"
        ]
      }
    },
    "/api/room/getRoomResourcesWithExamTypes/{token}": {
      "get": {
        "operationId": "RoomController_getRoomResourcesWithExamTypes",
        "parameters": [
          {
            "name": "token",
            "required": true,
            "in": "path",
            "description": "JWT token utilisateur",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Liste des salles avec types d'examens"
          },
          "401": {
            "description": "Token invalide ou expiré"
          }
        },
        "summary": "Salles (EasyDoct forwardé ; route config du contrat en saveur libre)",
        "tags": [
          "Room"
        ]
      }
    },
    "/api/kioskTicket/reserve": {
      "post": {
        "operationId": "KioskTicketController_reserve",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "kioskDeviceExternalId",
                  "officePlaceId",
                  "reservationUid"
                ],
                "properties": {
                  "kioskDeviceExternalId": {
                    "type": "string"
                  },
                  "officePlaceId": {
                    "type": "number"
                  },
                  "reservationUid": {
                    "type": "string",
                    "description": "Uid unique par tentative logique — même uid ⇒ même numéro"
                  },
                  "prefix": {
                    "type": "string",
                    "nullable": true,
                    "description": "Préfixe RDV calculé côté borne"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Réservation (number, formattedNumber, status)"
          }
        },
        "summary": "Réserver un numéro de ticket avant le check-in contrat (idempotent par reservationUid)",
        "tags": [
          "KioskTicket"
        ]
      }
    },
    "/api/kioskTicket/confirm": {
      "post": {
        "operationId": "KioskTicketController_confirm",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "reservationUid"
                ],
                "properties": {
                  "reservationUid": {
                    "type": "string"
                  },
                  "contractAppointmentId": {
                    "type": "string",
                    "nullable": true
                  },
                  "patientDisplayName": {
                    "type": "string",
                    "nullable": true,
                    "deprecated": true,
                    "description": "IGNORÉ — le nom du patient n'est jamais persisté (donnée sensible)"
                  },
                  "examLabel": {
                    "type": "string",
                    "nullable": true
                  },
                  "kioskCheckinAnomalyIds": {
                    "type": "array",
                    "items": {
                      "type": "integer"
                    },
                    "nullable": true
                  },
                  "nonEligibilityReason": {
                    "type": "integer",
                    "nullable": true,
                    "description": "Motif du refus d'accueil (référentiel éditeur) — affiché au Cockpit avec l'anomalie « Dossier Incomplet »"
                  },
                  "paramedicCheckIn": {
                    "type": "boolean",
                    "description": "Check-in effectué par un accompagnant/brancardier (mode paramédical)"
                  },
                  "pendingExternalCheckIn": {
                    "type": "boolean",
                    "description": "Accueil RIS différé : la borne n'a pas appelé le check-in du contrat (licence en enablePostKioskCheckInSystemNotify). Le ticket ressort dans l'onglet « À vérifier » du Cockpit, où l'accueil réel est déclenché."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Réservation confirmée"
          }
        },
        "summary": "Confirmer une réservation après succès du check-in (détails Suivi)",
        "tags": [
          "KioskTicket"
        ]
      }
    },
    "/api/kioskTicket/issueForAppointment": {
      "post": {
        "operationId": "KioskTicketController_issueForAppointment",
        "parameters": [
          {
            "name": "authorization",
            "required": true,
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "description": "brandAuthorizationKey de la licence (KioskReactorSetting)",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "officePlaceId",
                  "requestUid"
                ],
                "properties": {
                  "licenceUuid": {
                    "type": "string",
                    "nullable": true,
                    "description": "UUID de la licence ApiBorne — identification de RÉFÉRENCE (admin, page Connectivité), prime sur tout autre identifiant"
                  },
                  "officeVisibleId": {
                    "type": "string",
                    "nullable": true,
                    "description": "Uuid de l'office éditeur (EasyDoct : Office.VisibleId) — repli des intégrations historiques qui n'envoient pas le licenceUuid"
                  },
                  "brandId": {
                    "type": "string",
                    "nullable": true,
                    "description": "BrandId KioskReactor de la licence (requis sans officeVisibleId/licenceUuid ; sinon vérifié)"
                  },
                  "officeId": {
                    "type": "string",
                    "nullable": true,
                    "description": "Id office éditeur — repli legacy via integrationEasyDocts"
                  },
                  "officePlaceId": {
                    "type": "number",
                    "description": "Id du lieu de soins du RDV — sert à la séquence par lieu ET au décalage de numérotation configuré par lieu (Numéros de ticket)"
                  },
                  "requestUid": {
                    "type": "string",
                    "description": "Uid d'idempotence, UNIQUE PAR GÉNÉRATION (rejeu réseau seulement — une re-génération legacy consomme un nouveau numéro)"
                  },
                  "prefix": {
                    "type": "string",
                    "nullable": true,
                    "description": "Préfixe explicite (démo/compat). Absent → calculé ICI depuis la conf Mongo (enableTicketExamTypePrefix + examTypeTicketPrefixes, repli 2 lettres du type)"
                  },
                  "examTypeId": {
                    "type": "number",
                    "nullable": true,
                    "description": "Id du type d'examen (référentiel éditeur) — pour le préfixe calculé"
                  },
                  "examTypeLabel": {
                    "type": "string",
                    "nullable": true,
                    "description": "Libellé du type d'examen — repli du préfixe calculé"
                  },
                  "contractAppointmentId": {
                    "type": "string",
                    "nullable": true,
                    "description": "Id contrat du RDV ({id}~{visibleId})"
                  },
                  "patientDisplayName": {
                    "type": "string",
                    "nullable": true,
                    "deprecated": true,
                    "description": "IGNORÉ — le nom du patient n'est jamais persisté (donnée sensible)"
                  },
                  "examLabel": {
                    "type": "string",
                    "nullable": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "{ number, formattedNumber, day }"
          }
        },
        "summary": "Émettre un ticket pour une arrivée pointée dans EasyDoct (flag UseExternalConfiguration) — même séquence que la borne, ticket confirmé visible au Cockpit, idempotent par requestUid",
        "tags": [
          "KioskTicket"
        ]
      }
    },
    "/api/kioskTicket/appointmentStatusChanged": {
      "post": {
        "operationId": "KioskTicketController_appointmentStatusChanged",
        "parameters": [
          {
            "name": "authorization",
            "required": true,
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "description": "brandAuthorizationKey de la licence (KioskReactorSetting)",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "contractAppointmentId",
                  "status"
                ],
                "properties": {
                  "officeVisibleId": {
                    "type": "string",
                    "nullable": true,
                    "description": "Uuid de l'office éditeur — repli des intégrations historiques (licenceUuid prime)"
                  },
                  "licenceUuid": {
                    "type": "string",
                    "nullable": true,
                    "description": "UUID de la licence ApiBorne — identification de référence (admin, page Connectivité)"
                  },
                  "brandId": {
                    "type": "string",
                    "nullable": true,
                    "description": "Requis sans officeVisibleId/licenceUuid"
                  },
                  "officeId": {
                    "type": "string",
                    "nullable": true,
                    "description": "Repli legacy (integrationEasyDocts)"
                  },
                  "contractAppointmentId": {
                    "type": "string",
                    "description": "Id contrat du RDV ({id}~{visibleId})"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "scheduled",
                      "checkedIn",
                      "inCare",
                      "done",
                      "cancelled"
                    ],
                    "description": "État courant du RDV (référentiel contrat)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "{ updated: nombre de tickets mis à jour }"
          }
        },
        "summary": "Notification push d'EasyDoct (UseExternalConfiguration) à chaque changement d'état d'un RDV — met à jour externalStatus des tickets du jour, invalide le cache Cockpit et émet l'event Firestore",
        "tags": [
          "KioskTicket"
        ]
      }
    },
    "/api/kioskTicket/cancelForAppointment": {
      "post": {
        "operationId": "KioskTicketController_cancelForAppointment",
        "parameters": [
          {
            "name": "authorization",
            "required": true,
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "description": "brandAuthorizationKey de la licence (KioskReactorSetting)",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "contractAppointmentId"
                ],
                "properties": {
                  "officeVisibleId": {
                    "type": "string",
                    "nullable": true,
                    "description": "Uuid de l'office éditeur — repli des intégrations historiques (licenceUuid prime)"
                  },
                  "licenceUuid": {
                    "type": "string",
                    "nullable": true,
                    "description": "UUID de la licence ApiBorne — identification de référence (admin, page Connectivité)"
                  },
                  "brandId": {
                    "type": "string",
                    "nullable": true,
                    "description": "Requis sans officeVisibleId/licenceUuid"
                  },
                  "officeId": {
                    "type": "string",
                    "nullable": true,
                    "description": "Repli legacy (integrationEasyDocts)"
                  },
                  "contractAppointmentId": {
                    "type": "string",
                    "description": "Id contrat du RDV ({id}~{visibleId})"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "{ cancelled: nombre de tickets annulés }"
          }
        },
        "summary": "Annulation par l'éditeur des tickets du jour d'un RDV (refaire l'accueil) : tickets passés `cancelled`, retirés du Cockpit ; le prochain passage borne réserve un nouveau numéro",
        "tags": [
          "KioskTicket"
        ]
      }
    },
    "/api/kioskTicket/getCheckinNotifySettings": {
      "post": {
        "operationId": "KioskTicketController_getCheckinNotifySettings",
        "parameters": [
          {
            "name": "authorization",
            "required": true,
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "description": "brandAuthorizationKey de la licence (KioskReactorSetting)",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "officeVisibleId": {
                    "type": "string",
                    "nullable": true,
                    "description": "Uuid de l'office éditeur — repli des intégrations historiques (licenceUuid prime)"
                  },
                  "licenceUuid": {
                    "type": "string",
                    "nullable": true
                  },
                  "brandId": {
                    "type": "string",
                    "nullable": true,
                    "description": "Requis sans officeVisibleId/licenceUuid"
                  },
                  "officeId": {
                    "type": "string",
                    "nullable": true,
                    "description": "Repli legacy"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "{ settings: [entrée globale (officePlaceId null) + entrées par lieu], anomalies: référentiel ApiBorne (propres + globales) pour traduire excludedAnomalyCodes sans le référentiel EasyDoct }"
          }
        },
        "summary": "Réglages « Accueil RIS » (checkInSystemNotifySettings) de la licence, lus par EasyDoct quand UseExternalConfiguration est actif — la conf Mongo (admin ApiBorne) est la source de vérité des conditions de notification",
        "tags": [
          "KioskTicket"
        ]
      }
    },
    "/api/kioskTicket/printTicket": {
      "post": {
        "operationId": "KioskTicketController_printTicket",
        "parameters": [
          {
            "name": "authorization",
            "required": true,
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "description": "brandAuthorizationKey de la licence (KioskReactorSetting)",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "officePlaceId"
                ],
                "properties": {
                  "officeVisibleId": {
                    "type": "string",
                    "nullable": true,
                    "description": "Uuid de l'office éditeur (résolution prioritaire)"
                  },
                  "licenceUuid": {
                    "type": "string",
                    "nullable": true
                  },
                  "brandId": {
                    "type": "string",
                    "nullable": true
                  },
                  "officeId": {
                    "type": "string",
                    "nullable": true
                  },
                  "officePlaceId": {
                    "type": "number",
                    "description": "Lieu du RDV — sélectionne la borne cible"
                  },
                  "kioskDeskId": {
                    "type": "number",
                    "nullable": true,
                    "description": "Guichet du demandeur (id ApiBorne) — son imprimante bureau est prioritaire si configurée"
                  },
                  "userEmail": {
                    "type": "string",
                    "nullable": true,
                    "description": "Email du demandeur. Utilisé quand l'appelant est l'éditeur, dont les ids de guichet ne valent que dans son propre SQL : le guichet ApiBorne est alors retrouvé par l'utilisateur qui l'occupe (page Guichets de l'admin). Ignoré si kioskDeskId est fourni."
                  },
                  "language": {
                    "type": "string",
                    "nullable": true,
                    "description": "Variante de template (fr par défaut)"
                  },
                  "data": {
                    "type": "object",
                    "nullable": true,
                    "description": "Données Mustache du ticket (contexte minimal : numéro, patient, examen…) — clés dupliquées Pascal/camel au rendu"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "{ printed, deviceExternalId }"
          }
        },
        "summary": "Réimpression d'un ticket demandée par l'éditeur (UseExternalConfiguration) — template Mustache, borne cible et IP résolus depuis la conf Mongo, commande envoyée au cloud KioskReactor",
        "tags": [
          "KioskTicket"
        ]
      }
    },
    "/api/kioskTicket/reprintFromCockpit": {
      "post": {
        "operationId": "KioskTicketController_reprintFromCockpit",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "userSessionKey",
                  "kioskTicketId"
                ],
                "properties": {
                  "userSessionKey": {
                    "type": "string",
                    "description": "JWT de session Cockpit"
                  },
                  "kioskTicketId": {
                    "type": "number",
                    "description": "Id ApiBorne du ticket à réimprimer"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "{ printed, deviceExternalId }"
          }
        },
        "summary": "Réimpression d'un ticket depuis le Cockpit (saveur ApiBorne) — authentifiée par la session utilisateur, la clé de marque ne transite jamais par le navigateur",
        "tags": [
          "KioskTicket"
        ]
      }
    },
    "/api/kioskTicket/release": {
      "post": {
        "operationId": "KioskTicketController_release",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "reservationUid"
                ],
                "properties": {
                  "reservationUid": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Réservation relâchée"
          }
        },
        "summary": "Relâcher une réservation après échec du check-in (statut failed)",
        "tags": [
          "KioskTicket"
        ]
      }
    },
    "/api/kioskTicket/createKioskDeskRequest": {
      "post": {
        "operationId": "KioskTicketController_createKioskDeskRequest",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "kioskDeviceExternalId",
                  "officePlaceId",
                  "requestUid"
                ],
                "properties": {
                  "kioskDeviceExternalId": {
                    "type": "string"
                  },
                  "officePlaceId": {
                    "type": "number"
                  },
                  "requestUid": {
                    "type": "string"
                  },
                  "kioskDeskRequestReasonId": {
                    "type": "number",
                    "nullable": true
                  },
                  "cause": {
                    "type": "string"
                  },
                  "firstName": {
                    "type": "string"
                  },
                  "lastName": {
                    "type": "string"
                  },
                  "kioskRequestType": {
                    "type": "number",
                    "nullable": true,
                    "description": "1 = ticket de sortie (SOR), sinon REQ"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Forme legacy { appointmentTicketNumber, appointmentTicketNumberWithPrefix }"
          }
        },
        "summary": "Créer une demande guichet (numéro + persistance, forme legacy en retour, idempotent par requestUid)",
        "tags": [
          "KioskTicket"
        ]
      }
    },
    "/api/kioskTicket/getKioskTickets/{userSessionKey}": {
      "get": {
        "operationId": "KioskTicketController_getKioskTickets",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "day",
            "required": false,
            "in": "query",
            "description": "Jour YYYY-MM-DD (Europe/Paris)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Liste des tickets, tri heure desc"
          }
        },
        "summary": "Suivi admin : tickets RDV du jour (défaut jour courant, borné aux 7 derniers)",
        "tags": [
          "KioskTicket"
        ]
      }
    },
    "/api/kioskTicket/getKioskDeskRequests/{userSessionKey}": {
      "get": {
        "operationId": "KioskTicketController_getKioskDeskRequests",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "day",
            "required": false,
            "in": "query",
            "description": "Jour YYYY-MM-DD (Europe/Paris)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Liste des demandes, tri heure desc"
          }
        },
        "summary": "Suivi admin : demandes guichet du jour (défaut jour courant, borné aux 7 derniers)",
        "tags": [
          "KioskTicket"
        ]
      }
    },
    "/api/cockpit/signIn": {
      "post": {
        "operationId": "CockpitController_signIn",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "login",
                  "password"
                ],
                "properties": {
                  "login": {
                    "type": "string"
                  },
                  "password": {
                    "type": "string"
                  },
                  "sources": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "local",
                        "external"
                      ]
                    },
                    "description": "Sources à tenter (défaut : toutes)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "{ pendingSessionKey, offices: [{licenceId, name, officeId, officeVisibleId, useExternalConfiguration}] }"
          }
        },
        "summary": "Login Cockpit étape 1 : valide les identifiants et renvoie les licences accessibles. Le serveur gère toujours les deux sources ('local' = comptes ApiBorne, 'external' = éditeur via le contrat staff/sign-in) ; le client choisit celles à tenter via `sources`",
        "tags": [
          "Cockpit"
        ]
      }
    },
    "/api/cockpit/signInLicence": {
      "post": {
        "operationId": "CockpitController_signInLicence",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "pendingSessionKey",
                  "licenceId"
                ],
                "properties": {
                  "pendingSessionKey": {
                    "type": "string"
                  },
                  "licenceId": {
                    "type": "number"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "{ userSessionKey, userFirstNameLastName, email }"
          }
        },
        "summary": "Login Cockpit étape 2 : établit la session sur une licence (JWT userSessionKey)",
        "tags": [
          "Cockpit"
        ]
      }
    },
    "/api/cockpit/getOfficeConfig/{userSessionKey}": {
      "get": {
        "operationId": "CockpitController_getOfficeConfig",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "userConfig + kioskConfig.features + userAgendaSettings"
          }
        },
        "summary": "Équivalent minimal du officeConfig EasyDoct consommé par le Cockpit",
        "tags": [
          "Cockpit"
        ]
      }
    },
    "/api/cockpit/getKioskDeskId/{userSessionKey}": {
      "get": {
        "operationId": "CockpitController_getKioskDeskId",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "summary": "Guichet occupé par l'utilisateur + email",
        "tags": [
          "Cockpit"
        ]
      }
    },
    "/api/cockpit/getCallToKioskDeskKioskBoards/{userSessionKey}": {
      "get": {
        "operationId": "CockpitController_getBoards",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "summary": "Boards de la licence (AppointmentStatesList en tableau)",
        "tags": [
          "Cockpit"
        ]
      }
    },
    "/api/cockpit/getCallToKioskDeskKioskBoardCurrentUser/{userSessionKey}": {
      "get": {
        "operationId": "CockpitController_getCurrentUserBoard",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "summary": "Board lié au guichet occupé par l'utilisateur",
        "tags": [
          "Cockpit"
        ]
      }
    },
    "/api/cockpit/getKioskDesksWithAssociatedUsers/{userSessionKey}": {
      "get": {
        "operationId": "CockpitController_getKioskDesksWithAssociatedUsers",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "summary": "Guichets + utilisateur occupant (jointure cockpitUserSettings)",
        "tags": [
          "Cockpit"
        ]
      }
    },
    "/api/cockpit/updateTicketStatus": {
      "post": {
        "operationId": "CockpitController_updateTicketStatus",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "userSessionKey",
                  "kioskTicketId"
                ],
                "properties": {
                  "userSessionKey": {
                    "type": "string"
                  },
                  "kioskTicketId": {
                    "type": "number"
                  },
                  "status": {
                    "type": "string",
                    "description": "Défaut : 'next' (avance d'un cran)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "{ externalStatus }"
          }
        },
        "summary": "Change le statut du RDV lié à un ticket chez l'éditeur externe (contrat PUT /appointments/{id}/status) — status: 'next' | 'checkedIn' | 'inCare' | 'done'",
        "tags": [
          "Cockpit"
        ]
      }
    },
    "/api/cockpit/getKioskAppointments/{userSessionKey}": {
      "get": {
        "operationId": "CockpitController_getKioskAppointments",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "freshIds",
            "required": false,
            "in": "query",
            "description": "Ids (CSV) dont l'état vient de changer (signal Firestore) : ids tickets apiborne ou ids RDV éditeur — le cache de réconciliation est bypassé pour ces RDV",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "summary": "Tickets RDV du jour réconciliés avec l'agenda de l'éditeur externe (source de vérité) — annulés/supprimés exclus, externalStatus exposé",
        "tags": [
          "Cockpit"
        ]
      }
    },
    "/api/cockpit/updateUserAgendaDisplaySetting": {
      "post": {
        "operationId": "CockpitController_updateUserAgendaDisplaySetting",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "userSessionKey": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "{ HasError, kioskDeskIdModifed }"
          }
        },
        "summary": "Sauvegarde des réglages board de l'utilisateur (payload legacy)",
        "tags": [
          "Cockpit"
        ]
      }
    },
    "/api/cockpit/getKioskDeskRequests/{userSessionKey}/{officePlaceId}": {
      "get": {
        "operationId": "CockpitController_getKioskDeskRequests",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "officePlaceId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "summary": "Demandes guichet du jour d'un lieu (forme wire EasyDoct)",
        "tags": [
          "Cockpit"
        ]
      }
    },
    "/api/cockpit/getDeskRequestScanPageUrl/{userSessionKey}/{scanId}/{pageIndex}": {
      "get": {
        "operationId": "CockpitController_getDeskRequestScanPageUrl",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "scanId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pageIndex",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{ url, expiresAt }"
          },
          "404": {
            "description": "Scan inconnu pour cette licence, ou page hors du coffre"
          }
        },
        "summary": "Coffre documents : URL présignée (GET, 2 min, inline) d'une page d'ordonnance scannée — scan de la licence de la session uniquement",
        "tags": [
          "Cockpit"
        ]
      }
    },
    "/api/cockpit/callToKioskDeskRequest": {
      "post": {
        "operationId": "CockpitController_callToKioskDeskRequest",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "userSessionKey",
                  "kioskDeskRequestId"
                ],
                "properties": {
                  "userSessionKey": {
                    "type": "string"
                  },
                  "kioskDeskRequestId": {
                    "type": "number"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": ""
          }
        },
        "summary": "Appelle une demande au guichet occupé par l'utilisateur",
        "tags": [
          "Cockpit"
        ]
      }
    },
    "/api/cockpit/cancelCallToKioskDeskRequest": {
      "post": {
        "operationId": "CockpitController_cancelCallToKioskDeskRequest",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "userSessionKey",
                  "kioskDeskRequestId"
                ],
                "properties": {
                  "userSessionKey": {
                    "type": "string"
                  },
                  "kioskDeskRequestId": {
                    "type": "number"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": ""
          }
        },
        "summary": "Annule l'appel d'une demande (retour en attente)",
        "tags": [
          "Cockpit"
        ]
      }
    },
    "/api/cockpit/callTicketToDesk": {
      "post": {
        "operationId": "CockpitController_callTicketToDesk",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "userSessionKey",
                  "kioskTicketId"
                ],
                "properties": {
                  "userSessionKey": {
                    "type": "string"
                  },
                  "kioskTicketId": {
                    "type": "number"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": ""
          }
        },
        "summary": "Appelle un patient accueilli (ticket) au guichet occupé par l'utilisateur",
        "tags": [
          "Cockpit"
        ]
      }
    },
    "/api/cockpit/checkInTicketInExternalSystem": {
      "post": {
        "operationId": "CockpitController_checkInTicketInExternalSystem",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "userSessionKey",
                  "kioskTicketId"
                ],
                "properties": {
                  "userSessionKey": {
                    "type": "string"
                  },
                  "kioskTicketId": {
                    "type": "number"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Ticket mis à jour (pendingExternalCheckIn: false)"
          }
        },
        "summary": "Accueil RIS différé : déclenche le check-in du RDV chez l'éditeur (contrat) pour un ticket en attente",
        "tags": [
          "Cockpit"
        ]
      }
    },
    "/api/cockpit/cancelCallTicket": {
      "post": {
        "operationId": "CockpitController_cancelCallTicket",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "userSessionKey",
                  "kioskTicketId"
                ],
                "properties": {
                  "userSessionKey": {
                    "type": "string"
                  },
                  "kioskTicketId": {
                    "type": "number"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": ""
          }
        },
        "summary": "Annule l'appel d'un patient accueilli (retour en attente)",
        "tags": [
          "Cockpit"
        ]
      }
    },
    "/api/cockpit/togglePostCheckin": {
      "post": {
        "operationId": "CockpitController_togglePostCheckin",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "userSessionKey",
                  "kioskTicketId"
                ],
                "properties": {
                  "userSessionKey": {
                    "type": "string"
                  },
                  "kioskTicketId": {
                    "type": "number"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Ticket mis à jour (postCheckinCompleted basculé)"
          }
        },
        "summary": "Onglet « Accueilli borne » : bascule la validation post-accueil d'un ticket (prêt / pas prêt pour l'examen)",
        "tags": [
          "Cockpit"
        ]
      }
    },
    "/api/cockpit/updateKioskDeskRequest": {
      "post": {
        "operationId": "CockpitController_updateKioskDeskRequest",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "userSessionKey",
                  "Id"
                ],
                "properties": {
                  "userSessionKey": {
                    "type": "string"
                  },
                  "Id": {
                    "type": "number"
                  },
                  "Processed": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": ""
          }
        },
        "summary": "Met à jour une demande (bascule Processed)",
        "tags": [
          "Cockpit"
        ]
      }
    },
    "/api/kioskDeskRequestScan/uploadUrls": {
      "post": {
        "operationId": "KioskDeskRequestScanController_createUploadUrls",
        "parameters": [
          {
            "name": "x-kiosk-device-id",
            "required": true,
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-kiosk-auth-key",
            "required": true,
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Kiosk-Auth-Key",
            "in": "header",
            "description": "Clé de marque de la licence",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Kiosk-Device-Id",
            "in": "header",
            "description": "externalId de la borne",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "kioskDeviceExternalId",
                  "requestUid",
                  "scanUid",
                  "pages"
                ],
                "properties": {
                  "kioskDeviceExternalId": {
                    "type": "string"
                  },
                  "requestUid": {
                    "type": "string",
                    "description": "Uid de la demande guichet"
                  },
                  "scanUid": {
                    "type": "string",
                    "description": "Uid d'idempotence du scan (le même qu'à attach)"
                  },
                  "pages": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "required": [
                        "index",
                        "contentType",
                        "size"
                      ],
                      "properties": {
                        "index": {
                          "type": "number",
                          "example": 0
                        },
                        "contentType": {
                          "type": "string",
                          "enum": [
                            "image/jpeg",
                            "image/png"
                          ]
                        },
                        "size": {
                          "type": "number",
                          "description": "Octets (≤ SCAN_VAULT_MAX_PAGE_BYTES)"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "{ enabled, pages: [{ index, storageKey, uploadUrl, expiresAt }] } — seul Content-Type est un en-tête signé"
          },
          "401": {
            "description": "En-têtes borne absents ou clé de marque invalide"
          }
        },
        "summary": "Coffre documents : URLs présignées de dépôt (PUT direct S3) pour les pages d'un scan — { enabled: false } si le coffre n'est pas actif pour la licence",
        "tags": [
          "KioskDeskRequestScan"
        ]
      }
    },
    "/api/kioskDeskRequestScan/vaultIdentity": {
      "get": {
        "operationId": "KioskDeskRequestScanController_verifyVaultIdentity",
        "parameters": [
          {
            "name": "x-kiosk-device-id",
            "required": true,
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-kiosk-auth-key",
            "required": true,
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Kiosk-Auth-Key",
            "in": "header",
            "description": "Clé de marque de la licence",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Kiosk-Device-Id",
            "in": "header",
            "description": "externalId de la borne",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{ licenceId }"
          },
          "401": {
            "description": "En-têtes absents ou clé de marque invalide"
          },
          "404": {
            "description": "Borne inconnue"
          }
        },
        "summary": "Coffre documents : validation d'une identité de borne pour la passerelle (serveur → serveur) — renvoie { licenceId }",
        "tags": [
          "KioskDeskRequestScan"
        ]
      }
    },
    "/api/kioskDeskRequestScan/attach": {
      "post": {
        "operationId": "KioskDeskRequestScanController_attach",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "kioskDeviceExternalId",
                  "requestUid",
                  "scanUid",
                  "pages"
                ],
                "properties": {
                  "kioskDeviceExternalId": {
                    "type": "string"
                  },
                  "requestUid": {
                    "type": "string",
                    "description": "Uid de la demande guichet (KioskDeskRequest.requestUid)"
                  },
                  "scanUid": {
                    "type": "string",
                    "description": "Uid d'idempotence du scan"
                  },
                  "pages": {
                    "type": "array",
                    "description": "Pages scannées. Le fichier reste sur le disque de la borne : seul son nom est transmis.",
                    "items": {
                      "type": "object",
                      "properties": {
                        "filename": {
                          "type": "string",
                          "nullable": true,
                          "example": "capture_20260423_113027.jpg",
                          "description": "Nom du fichier sur la borne. Peut être absent pour une capture webcam déposée au coffre (storageKey obligatoire alors)"
                        },
                        "capturedAt": {
                          "type": "string",
                          "nullable": true
                        },
                        "documentDetected": {
                          "type": "boolean",
                          "nullable": true
                        },
                        "isBlurry": {
                          "type": "boolean",
                          "nullable": true
                        },
                        "captureQuality": {
                          "type": "number",
                          "nullable": true
                        },
                        "rotation": {
                          "type": "number",
                          "nullable": true
                        },
                        "cropped": {
                          "type": "boolean",
                          "nullable": true
                        },
                        "storageKey": {
                          "type": "string",
                          "nullable": true,
                          "description": "Coffre documents : clé renvoyée par uploadUrls, après PUT réussi. Vérifiée (préfixe + HEAD) ; absente du coffre ⇒ page conservée sans clé"
                        },
                        "contentType": {
                          "type": "string",
                          "nullable": true
                        },
                        "size": {
                          "type": "number",
                          "nullable": true
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Scan rattaché (ou scan existant si rejeu du scanUid) — pages avec `stored` (jamais de clé ni d’URL)"
          }
        },
        "summary": "Rattacher des pages scannées à une demande guichet (noms de fichiers, plus clé du coffre documents si la licence l'a activé ; idempotent par scanUid)",
        "tags": [
          "KioskDeskRequestScan"
        ]
      }
    },
    "/api/kioskDeskRequestScan/analysis": {
      "post": {
        "operationId": "KioskDeskRequestScanController_recordAnalysis",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "kioskDeviceExternalId",
                  "requestUid",
                  "status"
                ],
                "properties": {
                  "kioskDeviceExternalId": {
                    "type": "string"
                  },
                  "requestUid": {
                    "type": "string",
                    "description": "Uid de la demande guichet (KioskDeskRequest.requestUid)"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "analyzed",
                      "failed"
                    ]
                  },
                  "result": {
                    "type": "object",
                    "description": "Réponse STRUCTURÉE du service d'analyse : status métier, structuredAnswer, prescriberResolution, processDelayMs, errorMessage. Jamais le document.",
                    "properties": {
                      "status": {
                        "type": "string",
                        "nullable": true
                      },
                      "structuredAnswer": {
                        "type": "object",
                        "nullable": true
                      },
                      "prescriberResolution": {
                        "type": "object",
                        "nullable": true
                      },
                      "processDelayMs": {
                        "type": "number",
                        "nullable": true
                      },
                      "errorMessage": {
                        "type": "string",
                        "nullable": true
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Scan mis à jour avec son analyse"
          },
          "404": {
            "description": "Demande ou scan introuvable pour cette borne"
          }
        },
        "summary": "Déposer le résultat de l'analyse IA faite par la borne sur le scan d'une demande guichet (jamais d'image)",
        "tags": [
          "KioskDeskRequestScan"
        ]
      }
    },
    "/api/kioskDeskRequestScan/getScans/{userSessionKey}": {
      "get": {
        "operationId": "KioskDeskRequestScanController_getScans",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "day",
            "required": false,
            "in": "query",
            "description": "Jour YYYY-MM-DD (Europe/Paris)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Liste des scans, tri date desc"
          }
        },
        "summary": "Suivi admin : scans du jour (défaut jour courant, borné aux 7 derniers)",
        "tags": [
          "KioskDeskRequestScan"
        ]
      }
    },
    "/api/kioskDeskRequestScan/byRequest/{deskRequestId}/{userSessionKey}": {
      "get": {
        "operationId": "KioskDeskRequestScanController_getScanByRequest",
        "parameters": [
          {
            "name": "deskRequestId",
            "required": true,
            "in": "path",
            "description": "KioskDeskRequest.id",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "description": "JWT token utilisateur — mettre '-' pour s'authentifier par X-Licence-Uuid",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-licence-uuid",
            "required": true,
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Licence-Uuid",
            "in": "header",
            "description": "UUID de la licence — alternative au JWT (outil de test local)",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Le scan de la demande"
          },
          "404": {
            "description": "Aucun scan rattaché à cette demande"
          }
        },
        "summary": "Scan rattaché à UNE demande guichet (le plus récent). Outil de test d'analyse IA.",
        "tags": [
          "KioskDeskRequestScan"
        ]
      }
    },
    "/api/apiCallLog/logBatch": {
      "post": {
        "operationId": "ApiCallLogController_logBatch",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "kioskDeviceExternalId",
                  "entries"
                ],
                "properties": {
                  "kioskDeviceExternalId": {
                    "type": "string"
                  },
                  "entries": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "channel": {
                          "type": "string",
                          "enum": [
                            "contract",
                            "apiborne-ticket"
                          ]
                        },
                        "httpMethod": {
                          "type": "string"
                        },
                        "path": {
                          "type": "string"
                        },
                        "httpStatus": {
                          "type": "number",
                          "nullable": true
                        },
                        "durationMs": {
                          "type": "number"
                        },
                        "ok": {
                          "type": "boolean"
                        },
                        "errorCode": {
                          "type": "string",
                          "nullable": true
                        },
                        "encrypted": {
                          "type": "boolean"
                        },
                        "clientTs": {
                          "type": "number",
                          "description": "Epoch ms côté borne"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Lot persisté (HasError:false)"
          }
        },
        "summary": "Réception par lots des métadonnées d'appel de la borne (jamais de contenu)",
        "tags": [
          "ApiCallLog"
        ]
      }
    },
    "/api/apiCallLog/getApiCallLogs/{userSessionKey}": {
      "get": {
        "operationId": "ApiCallLogController_getApiCallLogs",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "channel",
            "required": false,
            "in": "query",
            "schema": {
              "enum": [
                "contract",
                "apiborne-ticket"
              ],
              "type": "string"
            }
          },
          {
            "name": "httpMethod",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ok",
            "required": false,
            "in": "query",
            "description": "true | false",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "deviceExternalId",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Liste des logs, tri clientTs desc"
          }
        },
        "summary": "Consultation admin : métadonnées d'appel de la licence courante (7 derniers jours)",
        "tags": [
          "ApiCallLog"
        ]
      }
    },
    "/elastic-admin/stats": {
      "get": {
        "description": "Par index : nb total de documents et nb de documents plus vieux que olderThanMonths. Sans licenceId : vision globale ; avec licenceId : cloisonné aux officeIds de la licence.",
        "operationId": "getElasticRetentionStats",
        "parameters": [
          {
            "name": "olderThanMonths",
            "required": false,
            "in": "query",
            "schema": {
              "example": 6,
              "type": "number"
            }
          },
          {
            "name": "licenceId",
            "required": false,
            "in": "query",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Stats par index (cutoff, total, olderThanCutoff)"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Statistiques de rétention Elastic (superadmin)",
        "tags": [
          "ElasticAdmin"
        ]
      }
    },
    "/elastic-admin/cleanup": {
      "post": {
        "description": "Supprime (deleteByQuery) les documents plus vieux que olderThanMonths (>= 1 obligatoire). Sans licenceId : clean GLOBAL ; avec licenceId : cloisonné aux officeIds de la licence.",
        "operationId": "runElasticRetentionCleanup",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "olderThanMonths": {
                    "type": "number",
                    "example": 6,
                    "minimum": 1
                  },
                  "licenceId": {
                    "type": "number",
                    "nullable": true,
                    "description": "Omis = clean global"
                  }
                },
                "required": [
                  "olderThanMonths"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Résultat par index (deleted)"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Ménage manuel des données Elastic anciennes (superadmin)",
        "tags": [
          "ElasticAdmin"
        ]
      }
    },
    "/licences/{licenceId}/kiosk-stats": {
      "get": {
        "operationId": "getKioskStats",
        "parameters": [
          {
            "name": "licenceId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "from",
            "required": true,
            "in": "query",
            "description": "Début de période (ISO 8601)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "required": true,
            "in": "query",
            "description": "Fin de période (ISO 8601)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "granularity",
            "required": true,
            "in": "query",
            "schema": {
              "enum": [
                "hour",
                "day",
                "week",
                "month"
              ],
              "type": "string"
            }
          },
          {
            "name": "officePlaceId",
            "required": false,
            "in": "query",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "deviceId",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Stats agrégées (voir KioskStatsResponse)"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Statistiques d'activité des bornes de la licence (KPI, séries temporelles Europe/Paris, par borne, langues)",
        "tags": [
          "KioskStats"
        ]
      }
    },
    "/licences/{licenceId}/kiosk-stats/desk-calls": {
      "get": {
        "operationId": "getDeskCallStats",
        "parameters": [
          {
            "name": "licenceId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "from",
            "required": true,
            "in": "query",
            "description": "Début de période (ISO 8601)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "required": true,
            "in": "query",
            "description": "Fin de période (ISO 8601)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "granularity",
            "required": true,
            "in": "query",
            "schema": {
              "enum": [
                "hour",
                "day",
                "week",
                "month"
              ],
              "type": "string"
            }
          },
          {
            "name": "officePlaceId",
            "required": false,
            "in": "query",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Stats agrégées (voir DeskCallStatsResponse)"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Statistiques des appels guichet de la licence (KPI, séries temporelles Europe/Paris, motifs, guichets, agents)",
        "tags": [
          "KioskStats"
        ]
      }
    },
    "/prescription-ai-stats": {
      "get": {
        "operationId": "getPrescriptionAiStats",
        "parameters": [
          {
            "name": "from",
            "required": true,
            "in": "query",
            "description": "Début de période (ISO 8601)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "required": true,
            "in": "query",
            "description": "Fin de période (ISO 8601)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "granularity",
            "required": true,
            "in": "query",
            "schema": {
              "enum": [
                "hour",
                "day",
                "week",
                "month"
              ],
              "type": "string"
            }
          },
          {
            "name": "licenceId",
            "required": false,
            "in": "query",
            "description": "Filtre de diagnostic ; absent = toutes licences",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Stats agrégées (voir PrescriptionAiStatsResponse)"
          },
          "403": {
            "description": "Réservé au superadmin"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Statistiques des analyses IA d'ordonnance (coût en tokens, taux de résolution du prescripteur, examens reconnus) — toutes licences, filtrable",
        "tags": [
          "KioskStats"
        ]
      }
    },
    "/support/contact": {
      "post": {
        "operationId": "SupportController_contact",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "example": "John Doe"
                  },
                  "email": {
                    "type": "string",
                    "example": "user@example.com"
                  },
                  "phone": {
                    "type": "string",
                    "example": "+33 6 12 34 56 78"
                  },
                  "message": {
                    "type": "string",
                    "example": "Bonjour, j’ai une question…"
                  }
                },
                "required": [
                  "email",
                  "message"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Message envoyé au support"
          },
          "400": {
            "description": "Email ou message manquant"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Envoyer un message au support",
        "tags": [
          "Support"
        ]
      }
    },
    "/support/public-contact": {
      "post": {
        "operationId": "PublicContactController_publicContact",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "example": "Marie Dupont"
                  },
                  "email": {
                    "type": "string",
                    "example": "marie.dupont@cabinet.fr"
                  },
                  "phone": {
                    "type": "string",
                    "example": "06 12 34 56 78"
                  },
                  "sector": {
                    "type": "string",
                    "example": "Cabinet de radiologie"
                  },
                  "message": {
                    "type": "string",
                    "example": "Je souhaite une démonstration."
                  },
                  "company": {
                    "type": "string",
                    "description": "Honeypot anti-spam : doit rester vide"
                  }
                },
                "required": [
                  "name",
                  "email",
                  "phone",
                  "sector",
                  "message"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Demande transmise"
          },
          "400": {
            "description": "Champs manquants ou invalides"
          },
          "429": {
            "description": "Trop de demandes depuis cette IP"
          }
        },
        "summary": "Envoyer une demande depuis le formulaire de contact public du site",
        "tags": [
          "Support"
        ]
      }
    },
    "/api/patient/officePlaceContext/{officeVisibleId}/{officePlaceVisibleId}": {
      "get": {
        "operationId": "PatientController_getOfficePlaceContext",
        "parameters": [
          {
            "name": "X-Licence-Uuid",
            "in": "header",
            "description": "UUID de la licence ApiBorne (saveur libre) — injecté par le Pass depuis ?licence=",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "officeVisibleId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "officePlaceVisibleId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "title",
            "required": true,
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{ officeVisibleId, officePlaceVisibleId, title? }"
          }
        },
        "summary": "Contexte lieu (echo du couple office/officePlace + titre optionnel)",
        "tags": [
          "Patient"
        ]
      }
    },
    "/api/patient/identify": {
      "post": {
        "operationId": "PatientController_identify",
        "parameters": [
          {
            "name": "X-Licence-Uuid",
            "in": "header",
            "description": "UUID de la licence ApiBorne (saveur libre) — injecté par le Pass depuis ?licence=",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-licence-uuid",
            "required": true,
            "in": "header",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "ticketNumber",
                  "birthDate",
                  "officePlaceVisibleId"
                ],
                "properties": {
                  "ticketNumber": {
                    "type": "string",
                    "description": "Numéro de ticket / code du RDV"
                  },
                  "birthDate": {
                    "type": "string",
                    "description": "DD/MM/YYYY ou YYYY-MM-DD"
                  },
                  "officePlaceVisibleId": {
                    "type": "string",
                    "description": "VisibleId du lieu où le ticket a été émis"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Une entrée par RDV du patient (vide si non trouvé/naissance KO)"
          },
          "429": {
            "description": "Trop de tentatives (par IP ou par ticket+lieu)"
          }
        },
        "summary": "Identifier par numéro de ticket + date de naissance (le ticket est un code getAppointmentByCode ; la naissance garde l’accès)",
        "tags": [
          "Patient"
        ]
      }
    },
    "/api/patient/appointmentByCode/{code}": {
      "get": {
        "operationId": "PatientController_getAppointmentByCode",
        "parameters": [
          {
            "name": "X-Licence-Uuid",
            "in": "header",
            "description": "UUID de la licence ApiBorne (saveur libre) — injecté par le Pass depuis ?licence=",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-licence-uuid",
            "required": true,
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "code",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "RDV (forme UI Pass)"
          },
          "404": {
            "description": "RDV introuvable"
          }
        },
        "summary": "RDV par code (QR / visibleId)",
        "tags": [
          "Patient"
        ]
      }
    },
    "/api/patient/appointment/{appointmentId}": {
      "get": {
        "operationId": "PatientController_getAppointmentById",
        "parameters": [
          {
            "name": "X-Licence-Uuid",
            "in": "header",
            "description": "UUID de la licence ApiBorne (saveur libre) — injecté par le Pass depuis ?licence=",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-licence-uuid",
            "required": true,
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appointmentId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "RDV (forme UI Pass)"
          },
          "404": {
            "description": "RDV introuvable"
          }
        },
        "summary": "RDV par id",
        "tags": [
          "Patient"
        ]
      }
    },
    "/api/patient/checkBirthDate": {
      "post": {
        "operationId": "PatientController_checkBirthDate",
        "parameters": [
          {
            "name": "X-Licence-Uuid",
            "in": "header",
            "description": "UUID de la licence ApiBorne (saveur libre) — injecté par le Pass depuis ?licence=",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-licence-uuid",
            "required": true,
            "in": "header",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "appointmentId",
                  "dateOfBirth"
                ],
                "properties": {
                  "appointmentId": {
                    "type": "string"
                  },
                  "dateOfBirth": {
                    "type": "string",
                    "description": "DD/MM/YYYY"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "{ valid: boolean }"
          },
          "429": {
            "description": "Trop de tentatives (par IP ou par RDV)"
          }
        },
        "summary": "Vérifier la date de naissance d’un RDV → { valid }",
        "tags": [
          "Patient"
        ]
      }
    },
    "/api/patient/appointment/{appointmentId}/documents": {
      "get": {
        "operationId": "PatientController_listDocuments",
        "parameters": [
          {
            "name": "X-Licence-Uuid",
            "in": "header",
            "description": "UUID de la licence ApiBorne (saveur libre) — injecté par le Pass depuis ?licence=",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-licence-uuid",
            "required": true,
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appointmentId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Documents + types requis (forme UI Pass)"
          }
        },
        "summary": "Documents du RDV + types requis",
        "tags": [
          "Patient"
        ]
      },
      "post": {
        "operationId": "PatientController_uploadDocument",
        "parameters": [
          {
            "name": "X-Licence-Uuid",
            "in": "header",
            "description": "UUID de la licence ApiBorne (saveur libre) — injecté par le Pass depuis ?licence=",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-licence-uuid",
            "required": true,
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appointmentId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "documentType",
                  "pagesContentBase64"
                ],
                "properties": {
                  "documentType": {
                    "type": "string",
                    "description": "Code contrat (vendor-neutral)"
                  },
                  "pagesContentBase64": {
                    "type": "string",
                    "description": "Pages base64 (sans préfixe data:) séparées par !#!"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "{ documentId }"
          }
        },
        "summary": "Téléverser un document (pages base64 séparées par !#!)",
        "tags": [
          "Patient"
        ]
      }
    },
    "/api/patient/appointment/{appointmentId}/documents/{documentId}": {
      "delete": {
        "operationId": "PatientController_deleteDocument",
        "parameters": [
          {
            "name": "X-Licence-Uuid",
            "in": "header",
            "description": "UUID de la licence ApiBorne (saveur libre) — injecté par le Pass depuis ?licence=",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-licence-uuid",
            "required": true,
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appointmentId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "documentId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Document supprimé"
          }
        },
        "summary": "Supprimer un document du RDV",
        "tags": [
          "Patient"
        ]
      }
    },
    "/api/patient/appointment/{appointmentId}/notificationContext": {
      "get": {
        "operationId": "PatientController_getNotificationContext",
        "parameters": [
          {
            "name": "X-Licence-Uuid",
            "in": "header",
            "description": "UUID de la licence ApiBorne (saveur libre) — injecté par le Pass depuis ?licence=",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-licence-uuid",
            "required": true,
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appointmentId",
            "required": true,
            "in": "path",
            "description": "Id contrat du RDV",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{ brandId, callToDeskBoardExternalId, stateBoardExternalId, appointmentId, ticketNumber, kioskTicketId, ticketFormatted }"
          },
          "404": {
            "description": "Aucun ticket borne pour ce RDV"
          }
        },
        "summary": "Contexte de notification d’appel guichet (brandId + boards + clés d’appariement du ticket)",
        "tags": [
          "Patient"
        ]
      }
    },
    "/api/patient/appointment/{appointmentId}/preparatorySurvey": {
      "get": {
        "operationId": "PatientController_ensurePreparatorySurvey",
        "parameters": [
          {
            "name": "X-Licence-Uuid",
            "in": "header",
            "description": "UUID de la licence ApiBorne (saveur libre) — injecté par le Pass depuis ?licence=",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-licence-uuid",
            "required": true,
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appointmentId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{ xId, name?, done }"
          }
        },
        "summary": "Résoudre/créer le questionnaire préparatoire du RDV (xId null si aucun)",
        "tags": [
          "Patient"
        ]
      }
    },
    "/api/patient/preparatorySurvey/{surveyResultId}": {
      "get": {
        "operationId": "PatientController_getPreparatorySurvey",
        "parameters": [
          {
            "name": "X-Licence-Uuid",
            "in": "header",
            "description": "UUID de la licence ApiBorne (saveur libre) — injecté par le Pass depuis ?licence=",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-licence-uuid",
            "required": true,
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "surveyResultId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "jsonDef + prefilledInfos + existingData + alreadyDone"
          }
        },
        "summary": "Charger la définition + données du questionnaire",
        "tags": [
          "Patient"
        ]
      },
      "post": {
        "operationId": "PatientController_sendPreparatorySurvey",
        "parameters": [
          {
            "name": "X-Licence-Uuid",
            "in": "header",
            "description": "UUID de la licence ApiBorne (saveur libre) — injecté par le Pass depuis ?licence=",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-licence-uuid",
            "required": true,
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "surveyResultId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "data"
                ],
                "properties": {
                  "data": {
                    "type": "object",
                    "description": "Résultat SurveyJS (nom → valeur)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Résultat enregistré (éléments pour le PDF)"
          }
        },
        "summary": "Soumettre les réponses du questionnaire",
        "tags": [
          "Patient"
        ]
      }
    },
    "/api/patient/preparatorySurvey/{surveyResultId}/pdf": {
      "post": {
        "operationId": "PatientController_uploadPreparatorySurveyPdf",
        "parameters": [
          {
            "name": "X-Licence-Uuid",
            "in": "header",
            "description": "UUID de la licence ApiBorne (saveur libre) — injecté par le Pass depuis ?licence=",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-licence-uuid",
            "required": true,
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "surveyResultId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "pdfBase64"
                ],
                "properties": {
                  "pdfBase64": {
                    "type": "string",
                    "description": "PDF encodé base64"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "PDF enregistré"
          }
        },
        "summary": "Téléverser le PDF du questionnaire rempli (base64)",
        "tags": [
          "Patient"
        ]
      }
    },
    "/mcp-tokens": {
      "get": {
        "operationId": "listMcpTokens",
        "parameters": [
          {
            "name": "licenceId",
            "required": false,
            "in": "query",
            "description": "Filtre superadmin uniquement",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tokens sans keyHash (keyPrefix seulement)"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Liste des tokens MCP (admin : sa licence ; superadmin : tous)",
        "tags": [
          "McpTokens"
        ]
      },
      "post": {
        "description": "Admin : token figé sur sa licence (licenceId refusé). Superadmin : licenceId pour un token figé sur une licence, omis pour un token global multi-licences. Quota : 5 tokens actifs par licence, 5 tokens globaux.",
        "operationId": "createMcpToken",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "label": {
                    "type": "string",
                    "example": "Claude Code — poste dev"
                  },
                  "expiresInDays": {
                    "type": "number",
                    "nullable": true,
                    "description": "Omis = sans expiration"
                  },
                  "licenceId": {
                    "type": "number",
                    "nullable": true,
                    "description": "Superadmin uniquement"
                  }
                },
                "required": [
                  "label"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "{ token, fullKey } — fullKey affichée une seule fois"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Crée un token MCP — la clé complète n’est retournée qu’ici, une seule fois",
        "tags": [
          "McpTokens"
        ]
      }
    },
    "/mcp-tokens/{id}/revoke": {
      "post": {
        "operationId": "revokeMcpToken",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Token révoqué"
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Révoque un token MCP (soft-revoke ; global : superadmin uniquement)",
        "tags": [
          "McpTokens"
        ]
      }
    },
    "/api/media/status": {
      "get": {
        "operationId": "getMediaStatus",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Le stockage S3 est-il configuré ?",
        "tags": [
          "Media"
        ]
      }
    },
    "/api/media/list": {
      "get": {
        "operationId": "listMedia",
        "parameters": [
          {
            "name": "licenceId",
            "required": true,
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Bibliothèque de la licence : dossiers + médias (URL publiques)",
        "tags": [
          "Media"
        ]
      }
    },
    "/api/media/fonts/catalog": {
      "get": {
        "operationId": "listGoogleFonts",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Polices Google Fonts proposées dans la page Thèmes",
        "tags": [
          "Media"
        ]
      }
    },
    "/api/media/fonts/install": {
      "post": {
        "operationId": "installGoogleFont",
        "parameters": [],
        "responses": {
          "201": {
            "description": ""
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Installe une police Google Fonts dans la médiathèque (auto-hébergement) et renvoie les entrées fonts[] du thème",
        "tags": [
          "Media"
        ]
      }
    },
    "/api/media/upload": {
      "post": {
        "operationId": "uploadMedia",
        "parameters": [
          {
            "name": "licenceId",
            "required": true,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "folder",
            "required": true,
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "201": {
            "description": ""
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Charge un média (multipart, champ « file » ; ?folder= optionnel)",
        "tags": [
          "Media"
        ]
      }
    },
    "/api/media/folder": {
      "post": {
        "operationId": "createMediaFolder",
        "parameters": [
          {
            "name": "licenceId",
            "required": true,
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "201": {
            "description": ""
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Crée un dossier (un niveau)",
        "tags": [
          "Media"
        ]
      },
      "delete": {
        "operationId": "deleteMediaFolder",
        "parameters": [
          {
            "name": "name",
            "required": true,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "licenceId",
            "required": true,
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Supprime un dossier VIDE (400 sinon)",
        "tags": [
          "Media"
        ]
      }
    },
    "/api/media/move": {
      "post": {
        "operationId": "moveMedia",
        "parameters": [
          {
            "name": "licenceId",
            "required": true,
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "201": {
            "description": ""
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Déplace un média vers un dossier (folder null/vide = racine)",
        "tags": [
          "Media"
        ]
      }
    },
    "/api/media": {
      "delete": {
        "operationId": "deleteMedia",
        "parameters": [
          {
            "name": "key",
            "required": true,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "licenceId",
            "required": true,
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "security": [
          {
            "bearer": []
          }
        ],
        "summary": "Supprime un média (par clé S3)",
        "tags": [
          "Media"
        ]
      }
    },
    "/api/kioskTranslate/batch": {
      "post": {
        "operationId": "KioskTranslate_Batch",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "summary": "Traduire un lot de textes fr vers une langue du pool produit (cache Mongo)",
        "tags": [
          "KioskTranslate"
        ]
      }
    },
    "/api/prescriber/search/{userSessionKey}": {
      "get": {
        "operationId": "PrescriberController_search",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "description": "JWT token utilisateur — mettre '-' pour s'authentifier par X-Licence-Uuid",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-licence-uuid",
            "required": true,
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "rppsId",
            "required": false,
            "in": "query",
            "description": "RPPS lu sur l'ordonnance",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lastName",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "firstName",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "town",
            "required": false,
            "in": "query",
            "description": "Commune lue sur l'ordonnance — DISCRIMINANT de dernier recours, jamais un critère (32,9 % du référentiel n'a aucune commune)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Défaut et plafond : 20",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Licence-Uuid",
            "in": "header",
            "description": "UUID de la licence — alternative au JWT (service local de la borne)",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Propriétés `matches` (PractitionerRef + lieu), `strategy`, `reason`"
          },
          "400": {
            "description": "Aucun critère exploitable (rppsId ou lastName requis)"
          },
          "401": {
            "description": "Authentification manquante ou invalide"
          }
        },
        "summary": "Recherche un prescripteur dans le référentiel RPPS public (RPPS prioritaire, nom en repli, commune en discriminant seulement)",
        "tags": [
          "Prescriber"
        ]
      }
    },
    "/api/prescriber/browse/{userSessionKey}": {
      "get": {
        "operationId": "PrescriberController_browse",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "description": "JWT token utilisateur",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "rppsId",
            "required": false,
            "in": "query",
            "description": "RPPS, même partiel (début de numéro)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lastName",
            "required": false,
            "in": "query",
            "description": "Début du nom (casse/accents indifférents)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "firstName",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "town",
            "required": false,
            "in": "query",
            "description": "Début de la commune",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "professionCode",
            "required": false,
            "in": "query",
            "description": "10 · 40 · 50",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "À partir de 1",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pageSize",
            "required": false,
            "in": "query",
            "description": "Défaut 25, plafond 100",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "`rows`, `total`, `totalIsCapped`, `page`, `pageSize`, `referentialReady`"
          },
          "401": {
            "description": "Token invalide ou expiré"
          },
          "403": {
            "description": "Réservé au superadmin"
          }
        },
        "summary": "CONSULTATION paginée du référentiel RPPS — page Prescripteurs de l'admin. SUPERADMIN uniquement (référentiel GLOBAL, partagé par toutes les licences).",
        "tags": [
          "Prescriber"
        ]
      }
    },
    "/api/prescriber/status/{userSessionKey}": {
      "get": {
        "operationId": "PrescriberController_status",
        "parameters": [
          {
            "name": "userSessionKey",
            "required": true,
            "in": "path",
            "description": "JWT token utilisateur — mettre '-' pour s'authentifier par X-Licence-Uuid",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-licence-uuid",
            "required": true,
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Licence-Uuid",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Propriétés `ready` (false = import jamais passé, distinct de « aucun résultat »), `count`, `extractionDate`, `attribution`"
          }
        },
        "summary": "État du référentiel RPPS : peuplé ou non, date de l'extraction ANS, dernier import",
        "tags": [
          "Prescriber"
        ]
      }
    },
    "/api/prescription-ai/health": {
      "get": {
        "operationId": "PrescriptionAiController_health",
        "parameters": [],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "summary": "État de l'analyse IA (sans appel Azure, donc sans coût)",
        "tags": [
          "PrescriptionAi"
        ]
      }
    },
    "/api/prescription-ai/analyzeDocument": {
      "post": {
        "operationId": "PrescriptionAiController_analyzeDocument",
        "parameters": [
          {
            "name": "refresh",
            "required": true,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "documentId",
            "required": true,
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Analyse (status ok) — forme du service local"
          },
          "401": {
            "description": "Borne non authentifiée"
          },
          "404": {
            "description": "Document absent ou inexploitable (file-not-found)"
          },
          "500": {
            "description": "not-configured · ai-failed · ai-unreadable"
          }
        },
        "summary": "Analyse IA d'une ordonnance fournie en base64 (mini-borne) — même contrat que POST /analyzeDocument du service local tools/prescription-ai",
        "tags": [
          "PrescriptionAi"
        ]
      }
    }
  },
  "info": {
    "title": "API ApiBorne",
    "description": "API de gestion des utilisateurs, licences et authentification",
    "version": "1.0",
    "contact": {}
  },
  "tags": [],
  "servers": [],
  "components": {
    "securitySchemes": {
      "bearer": {
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "type": "http"
      }
    },
    "schemas": {
      "XKioskDeviceDto": {
        "type": "object",
        "properties": {}
      },
      "XKioskConfigDto": {
        "type": "object",
        "properties": {
          "KioskReactorSetting": {
            "type": "object",
            "description": "Bloc KioskReactorSetting (feuilles camelCase)"
          },
          "KioskReactorSettingFeatures": {
            "type": "object"
          },
          "KioskReactorSettingMessages": {
            "type": "object"
          },
          "KioskReactorSettingPrinterCodes": {
            "type": "object"
          },
          "KioskReactorSettingCheckinAppointmentDetail": {
            "type": "object",
            "description": "Détail check-in global (officePlaceId null)"
          },
          "KioskReactorSettingCheckinAppointmentDetails": {
            "description": "Détails check-in par lieu du device",
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "KioskReactorDirectAdmissionSetting": {
            "type": "object"
          },
          "KioskReactorSettingDisplay": {
            "type": "object"
          },
          "KioskReactorSettingPatientInfoBookingOptions": {
            "type": "object"
          },
          "KioskReactorSettingRequestMessages": {
            "description": "Messages de demande guichet par lieu (requestMessageModel)",
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "KioskReactorSettingWrongPlaceMessageDetails": {
            "description": "Messages « mauvais lieu » par lieu (wrongPlaceMessageModel)",
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "KioskReactorSettingPatientLateAnomalies": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "KioskReactorSettingPatientAgeAnomalies": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "KioskReactorSettingRequiredDocumentLabels": {
            "description": "XKioskRequiredDocumentLabel[] (PascalCase : AppointmentFileType, CustomLabel, AvailableOnPhone)",
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        },
        "required": [
          "KioskReactorSetting",
          "KioskReactorSettingFeatures",
          "KioskReactorSettingMessages",
          "KioskReactorSettingPrinterCodes",
          "KioskReactorSettingCheckinAppointmentDetail",
          "KioskReactorSettingCheckinAppointmentDetails",
          "KioskReactorDirectAdmissionSetting",
          "KioskReactorSettingDisplay",
          "KioskReactorSettingPatientInfoBookingOptions",
          "KioskReactorSettingRequestMessages",
          "KioskReactorSettingWrongPlaceMessageDetails",
          "KioskReactorSettingPatientLateAnomalies",
          "KioskReactorSettingPatientAgeAnomalies",
          "KioskReactorSettingRequiredDocumentLabels"
        ]
      },
      "XKioskAnomalyByExternalIdDto": {
        "type": "object",
        "properties": {
          "Global": {
            "type": "boolean",
            "description": "Anomalie commune (non liée à une licence)"
          },
          "Description": {
            "type": "string",
            "nullable": true
          },
          "Name": {
            "type": "string"
          },
          "Color": {
            "type": "string",
            "nullable": true
          },
          "Code": {
            "type": "string",
            "nullable": true,
            "description": "Code métier vendor-neutral (ex 'DI', 'PR')"
          },
          "Id": {
            "type": "number"
          },
          "KeepForAppointment": {
            "type": "boolean"
          }
        },
        "required": [
          "Global",
          "Name",
          "Id",
          "KeepForAppointment"
        ]
      },
      "XKioskDeviceInfoDto": {
        "type": "object",
        "properties": {
          "kioskDevice": {
            "$ref": "#/components/schemas/XKioskDeviceDto"
          },
          "kioskConfig": {
            "nullable": true,
            "description": "null si la licence du device n’a pas de KioskReactorSetting",
            "allOf": [
              {
                "$ref": "#/components/schemas/XKioskConfigDto"
              }
            ]
          },
          "kioskAnomalies": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/XKioskAnomalyByExternalIdDto"
            }
          },
          "kioskDeskRequestReasons": {
            "description": "Motifs de requête guichet (clé ApiBorne, absente de la réponse EasyDoct) — champs PascalCase legacy (Id, Name, Description, PrintTicket, OfficePlaceIds…), ordonnés par la chaîne Previous/Next",
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        },
        "required": [
          "kioskDevice",
          "kioskAnomalies"
        ]
      },
      "GetKioskDeviceByExternalIdResultDto": {
        "type": "object",
        "properties": {
          "kioskDeviceInfo": {
            "$ref": "#/components/schemas/XKioskDeviceInfoDto"
          }
        }
      }
    }
  }
}