{"openapi": "3.1.0", "info": {"title": "API Kanadr", "description": "API publique : tout ce que fait le portail passe par elle.\n\n**Lecture seule** : licence de la plateforme échue depuis plus de 30 jours, toute écriture (`POST`, `PUT`, `PATCH`, `DELETE`) répond 403 `licence_lecture_seule`, sauf la connexion et la sécurité du compte, l'usage téléphonique d'un utilisateur (renvois, ne pas déranger, messages vocaux, appareils mobiles), le chargement de la licence et quelques gestes d'exploitation de l'opérateur (déblocage d'une adresse, rechargement, réenregistrement d'un trunk). Les lectures restent permises et la téléphonie n'est jamais coupée.", "license": {"name": "LicenseRef-Kanadr-Commercial", "identifier": "LicenseRef-Kanadr-Commercial"}, "version": "0.5.0"}, "paths": {"/api/v1/assistant": {"get": {"tags": ["assistant"], "summary": "L'assistant pour le compte connecté : disponible, budget atteint.", "operationId": "etatAssistant", "responses": {"200": {"description": "État de l'assistant", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/EtatAssistant"}}}}, "403": {"description": "`interdit` (permission `assistant.utiliser`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "post": {"tags": ["assistant"], "summary": "Converse avec l'assistant : envoie la conversation (et la réponse à une écriture en attente),\nreçoit la conversation à jour. Les outils de lecture s'exécutent d'eux-mêmes ; une écriture\ns'arrête en attente de confirmation.", "operationId": "converserAssistant", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/Conversation"}}}, "required": true}, "responses": {"200": {"description": "Conversation à jour", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReponseAssistant"}}}}, "403": {"description": "`interdit` (permission `assistant.utiliser`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : assistant non réglé par l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`assistant_desactive` : assistant IA coupé par l'opérateur (D94)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`conversation_invalide` : messages mal formés, ou écriture en attente sans confirmation", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "502": {"description": "`assistant_injoignable` : Claude injoignable ou en erreur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/cles-api/{id}": {"delete": {"tags": ["cles-api"], "summary": "Révoque une clé d'API, définitivement.", "operationId": "revoquerCleApi", "parameters": [{"name": "id", "in": "path", "description": "Clé", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"204": {"description": "Clé révoquée"}, "403": {"description": "`interdit`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}": {"get": {"tags": ["clients"], "summary": "Un client.", "operationId": "lireClient", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Client"}}}}, "403": {"description": "`interdit` (permission `client.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas un client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "delete": {"tags": ["clients"], "summary": "Résilie un client : postes, messageries, connecteurs SIP, parcours, répertoire et domaine\nSIP supprimés, avec leurs fichiers (annonces, messages, enregistrements, musique) ;\ncomptes, clés d'API et webhook supprimés. Définitif. L'organisation reste (désactivée,\ndatée) pour le journal d'audit et les CDR des mois passés. Refusé tant que le client a des\nnuméros (les retirer : ils reviennent au stock) ou un trunk (le supprimer). Réservé au\nniveau supérieur.", "operationId": "resilierClient", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"204": {"description": "Client résilié"}, "403": {"description": "`interdit` : permission `client.modifier`, ou compte du client lui-même", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas un client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`client_avec_numeros` (numéros à retirer d'abord), `client_avec_trunk` (trunk à supprimer d'abord)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "patch": {"tags": ["clients"], "summary": "Renomme, suspend ou réactive un client, règle l'enregistrement de ses appels (D111) ou\nl'ajout d'utilisateurs et de postes par son admin (D121).\nSuspendu : ses comptes ne se connectent plus (sessions fermées), ses clés d'API ne passent\nplus, ses téléphones ne s'enregistrent plus et ses numéros ne sonnent plus (domaine SIP\nhors service), il ne compte plus pour la licence (D71). Tout reste en place pour la\nréactivation. Réservé au niveau supérieur (opérateur, revendeur du client).", "operationId": "modifierClient", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/ModificationClient"}}}, "required": true}, "responses": {"204": {"description": "Client modifié"}, "403": {"description": "`interdit` : permission `client.modifier`, ou compte du client lui-même ; `licence_bloquee` : réactivation refusée, licence échue depuis plus de 30 jours (D78)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas un client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`numero_deja_route` : le parcours réécrit (enregistrement changé) route un numéro déjà routé ailleurs", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`nom_invalide`, `texte_interdit`, `parcours_invalide` (le parcours publié ne se réécrit pas)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/annonces": {"get": {"tags": ["parcours"], "summary": "Annonces déposées pour les modules du parcours publié et du brouillon.", "operationId": "listerAnnonces", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Annonces déposées", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/AnnonceDeposee"}}}}}, "403": {"description": "`interdit` (permission `parcours.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/annonces/{nature}/{cible}": {"get": {"tags": ["parcours"], "summary": "Écoute d'une annonce : le WAV tel que le moteur de téléphonie le joue.", "operationId": "ecouterAnnonce", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "nature", "in": "path", "description": "Nature de l'annonce", "required": true, "schema": {"$ref": "#/components/schemas/Nature"}}, {"name": "cible", "in": "path", "description": "Numéro interne du module, ou E.164 du numéro", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "WAV mono 16 bits 8 kHz", "content": {"audio/wav": {"schema": {"type": "array", "items": {"type": "integer", "format": "int32", "minimum": 0}}}}}, "403": {"description": "`interdit` (permission `parcours.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client ou annonce", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`annonce_invalide`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["parcours"], "summary": "Dépose une annonce : le fichier (WAV, MP3, AAC/M4A, Ogg Vorbis, FLAC ; 20 Mo, 10 minutes au\nplus) est converti en WAV mono 16 bits 8 kHz et remplace l'éventuelle annonce en place. La\nversion publiée du parcours est réécrite pour la citer (sans nouvelle version).", "operationId": "deposerAnnonce", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "nature", "in": "path", "description": "Nature de l'annonce", "required": true, "schema": {"$ref": "#/components/schemas/Nature"}}, {"name": "cible", "in": "path", "description": "Numéro interne du module, ou E.164 du numéro", "required": true, "schema": {"type": "string"}}, {"name": "format", "in": "query", "description": "Extension du fichier d'origine (`mp3`, `m4a`…) : aide à reconnaître le format.", "required": false, "schema": {"type": ["string", "null"]}}], "requestBody": {"description": "Fichier audio", "content": {"application/octet-stream": {"schema": {"type": "array", "items": {"type": "integer", "format": "int32", "minimum": 0}}}}, "required": true}, "responses": {"200": {"description": "Annonce en place", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AnnonceDeposee"}}}}, "403": {"description": "`interdit` (permission `parcours.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`numero_deja_route` : le parcours réécrit route un numéro déjà routé ailleurs", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "413": {"description": "`annonce_trop_grosse` : plus de 20 Mo", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`annonce_invalide`, `audio_illisible` (format non reconnu), `audio_vide`, `audio_trop_long` (plus de 10 minutes), `numero_inconnu` (pas un numéro du client), `parcours_invalide`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "delete": {"tags": ["parcours"], "summary": "Retire une annonce ; la version publiée du parcours cesse de la citer.", "operationId": "retirerAnnonce", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "nature", "in": "path", "description": "Nature de l'annonce", "required": true, "schema": {"$ref": "#/components/schemas/Nature"}}, {"name": "cible", "in": "path", "description": "Numéro interne du module, ou E.164 du numéro", "required": true, "schema": {"type": "string"}}], "responses": {"204": {"description": "Annonce retirée"}, "403": {"description": "`interdit` (permission `parcours.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client ou annonce", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`numero_deja_route`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`annonce_invalide`, `parcours_invalide`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/appareils": {"get": {"tags": ["materiel"], "summary": "Téléphones de bureau du client ; avec `poste`, ceux qui portent ce poste (ouvert à son\ntitulaire).", "operationId": "listerAppareils", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "poste", "in": "query", "description": "Les téléphones de ce poste seulement (ouvert à son titulaire).", "required": false, "schema": {"type": ["string", "null"]}}], "responses": {"200": {"description": "Appareils", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/AppareilMateriel"}}}}}, "403": {"description": "`interdit` (permission `poste.provisionner` sur le client, ou titulaire du poste demandé)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas un client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "post": {"tags": ["materiel"], "summary": "Ajoute un téléphone de bureau (ou une base DECT) à un client, avec ses comptes. Une MAC est\nunique sur l'instance : celle d'un autre client est refusée (on grefferait un compte sur le\ntéléphone d'un tiers).", "operationId": "ajouterAppareil", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/NouvelAppareil"}}}, "required": true}, "responses": {"201": {"description": "Appareil", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AppareilMateriel"}}}}, "403": {"description": "`interdit` (permission `poste.provisionner` sur le client ; paramètres supplémentaires : compte de l'opérateur ou d'un revendeur ; jamais par l'assistant ni le MCP)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client ou profil", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`appareil_mac_utilisee` : MAC déjà enregistrée (chez ce client ou un autre)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`appareil_invalide` : MAC, modèle, lignes, combinés ou touches invalides ; `parametres_invalides`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/appareils/{id}": {"delete": {"tags": ["materiel"], "summary": "Retire un appareil et tous ses comptes (pour une base DECT partagée, tous ses combinés).", "operationId": "retirerAppareil", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "id", "in": "path", "description": "Appareil", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"204": {"description": "Retiré"}, "403": {"description": "`interdit` (permission `poste.provisionner` sur le client ; jamais par l'assistant ni le MCP)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "patch": {"tags": ["materiel"], "summary": "Modifie un appareil : nom, numéro de série, modèle (du même profil), touches, paramètres\nsupplémentaires (opérateur et revendeur seulement).", "operationId": "modifierAppareil", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "id", "in": "path", "description": "Appareil", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/ModificationAppareil"}}}, "required": true}, "responses": {"200": {"description": "Appareil", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AppareilMateriel"}}}}, "403": {"description": "`interdit` (permission `poste.provisionner` sur le client ; paramètres supplémentaires : compte de l'opérateur ou d'un revendeur ; jamais par l'assistant ni le MCP)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`appareil_invalide` : modèle, touches ; `parametres_invalides`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/appareils/{id}/identifiants": {"post": {"tags": ["provisionnement"], "summary": "Révèle les identifiants HTTP de l'appareil, pour le configurer à la main (comme D114) : à\nqui peut installer les téléphones du client, jamais par l'assistant ni le MCP ; chaque\nrévélation est au journal d'audit, sans le mot de passe. `POST` et `no-store`.", "operationId": "revelerIdentifiantsAppareil", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "id", "in": "path", "description": "Appareil", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Identifiants", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/IdentifiantsAppareil"}}}}, "403": {"description": "`interdit` (permission `poste.provisionner` sur le client ; jamais par l'assistant ni le MCP)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/appareils/{id}/identifiants/renouveler": {"post": {"tags": ["provisionnement"], "summary": "Renouvelle le mot de passe HTTP de l'appareil (après la perte du téléphone, par exemple) :\nl'appareil ne lit plus sa configuration tant qu'on ne lui a pas donné le nouveau.", "operationId": "renouvelerIdentifiantsAppareil", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "id", "in": "path", "description": "Appareil", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"204": {"description": "Renouvelé (le nouveau se révèle avec `revelerIdentifiantsAppareil`)"}, "403": {"description": "`interdit` (permission `poste.provisionner` sur le client ; jamais par l'assistant ni le MCP)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/appareils/{id}/lignes": {"post": {"tags": ["materiel"], "summary": "Pose un compte de plus sur un appareil (un combiné de plus sur une base DECT partagée).", "operationId": "ajouterLigneAppareil", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "id", "in": "path", "description": "Appareil", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/NouvelleLigne"}}}, "required": true}, "responses": {"200": {"description": "Appareil", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AppareilMateriel"}}}}, "403": {"description": "`interdit` (permission `poste.provisionner` sur le client ; jamais par l'assistant ni le MCP)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`ligne_occupee` : rang ou combiné déjà pris", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`appareil_invalide` : rang, combiné ou poste invalide", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/appareils/{id}/lignes/{rang}": {"delete": {"tags": ["materiel"], "summary": "Retire un seul compte d'un appareil : les autres (combinés d'une même base) restent.", "operationId": "retirerLigneAppareil", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "id", "in": "path", "description": "Appareil", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "rang", "in": "path", "description": "Rang du compte", "required": true, "schema": {"type": "integer", "format": "int32", "minimum": 0}}], "responses": {"200": {"description": "Appareil", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AppareilMateriel"}}}}, "403": {"description": "`interdit` (permission `poste.provisionner` sur le client ; jamais par l'assistant ni le MCP)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : appareil ou ligne", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/appareils/{id}/redemarrer": {"post": {"tags": ["materiel"], "summary": "Demande au téléphone de redémarrer (NOTIFY de redémarrage du profil) : opérateur, revendeur,\nadmin du client ; pas le titulaire.", "operationId": "redemarrerAppareil", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "id", "in": "path", "description": "Appareil", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"204": {"description": "Demande envoyée au téléphone"}, "403": {"description": "`interdit` (permission `poste.provisionner` sur le client ; jamais par l'assistant ni le MCP)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`appareil_non_enregistre` : le téléphone n'est pas enregistré", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`appareil_commande_inconnue` : le profil ne sait pas redémarrer ses téléphones ; `appareil_invalide` : aucun poste sur le téléphone", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "503": {"description": "`moteur_injoignable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/appareils/{id}/requetes": {"get": {"tags": ["materiel"], "summary": "Dernières demandes reçues de l'appareil par le service des fichiers (diagnostic : fichier,\nréponse, adresse, agent).", "operationId": "listerRequetesAppareil", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "id", "in": "path", "description": "Appareil", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Demandes, de la plus récente à la plus ancienne", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/RequeteAppareil"}}}}}, "403": {"description": "`interdit` (permission `poste.provisionner` sur le client)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/appareils/{id}/resynchroniser": {"post": {"tags": ["materiel"], "summary": "Demande au téléphone de relire sa configuration (NOTIFY de resynchronisation du profil). Le\ntitulaire d'un poste qu'il porte peut le demander.", "operationId": "resynchroniserAppareil", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "id", "in": "path", "description": "Appareil", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"204": {"description": "Demande envoyée au téléphone"}, "403": {"description": "`interdit` (permission `poste.provisionner` sur le client, ou titulaire d'un poste du téléphone ; jamais par l'assistant ni le MCP)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`appareil_non_enregistre` : le téléphone n'est pas enregistré (il relira sa configuration à son prochain démarrage)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`appareil_invalide` : aucun poste sur le téléphone", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "503": {"description": "`moteur_injoignable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/appareils/{id}/rps": {"post": {"tags": ["materiel"], "summary": "Déclare (ou déclare de nouveau, après un échec) un appareil au RPS : un appareil d'un profil\nYealink, avec son numéro de série.", "operationId": "declarerAppareilRps", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "id", "in": "path", "description": "Appareil", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Appareil, avec l'état de sa déclaration (`rps_etat`, `rps_message`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AppareilMateriel"}}}}, "403": {"description": "`interdit` (permission `poste.provisionner` sur le client ; jamais par l'assistant ni le MCP)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`appareil_invalide` : profil sans RPS, ou numéro de série absent", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/appels": {"get": {"tags": ["journal"], "summary": "Journal d'appels du client.", "operationId": "listerAppels", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "du", "in": "query", "description": "Début de la période (RFC 3339), inclus.", "required": false, "schema": {"type": ["string", "null"], "format": "date-time"}}, {"name": "au", "in": "query", "description": "Fin de la période (RFC 3339), exclue.", "required": false, "schema": {"type": ["string", "null"], "format": "date-time"}}, {"name": "sens", "in": "query", "description": "`entrant`, `sortant` ou `interne`.", "required": false, "schema": {"type": ["string", "null"]}}, {"name": "poste", "in": "query", "description": "Appels d'un poste ; le titulaire du poste voit les siens.", "required": false, "schema": {"type": ["string", "null"]}}, {"name": "limite", "in": "query", "description": "Appels par page (100 par défaut, 500 au plus).", "required": false, "schema": {"type": ["integer", "null"], "format": "int64"}}, {"name": "avant", "in": "query", "description": "Page suivante : `suivant` de la page précédente.", "required": false, "schema": {"type": ["string", "null"], "format": "date-time"}}, {"name": "numeros", "in": "query", "description": "`complets` : numéros en entier (permission `journal.voir_numeros`, tracé).", "required": false, "schema": {"type": ["string", "null"]}}, {"name": "repondu", "in": "query", "description": "Vrai : appels répondus (un entrant mis en relation avec une personne, D66) ; faux : appels\nmanqués (ni mis en relation ni message) et sortants sans réponse.", "required": false, "schema": {"type": ["boolean", "null"]}}, {"name": "issue", "in": "query", "description": "Issue (D66) : `repondu`, `manque` ou `message` (entrant), `sans_reponse` (sortant ou\ninterne non décroché).", "required": false, "schema": {"type": ["string", "null"]}}, {"name": "duree_min", "in": "query", "description": "Durée minimale, en secondes décrochées.", "required": false, "schema": {"type": ["integer", "null"], "format": "int32"}}, {"name": "mois", "in": "query", "description": "Mois `AAAA-MM` à l'heure de Paris (export du parc) : remplace `du` et `au`, comme la\nconsommation.", "required": false, "schema": {"type": ["string", "null"]}}, {"name": "recherche", "in": "query", "description": "Recherche (100 caractères au plus) : un numéro, même partiel, saisi en national (`06…`),\nen `00…` ou en `+33…`, un poste, ou le nom d'un contact (poste, répertoire commun,\ncontacts personnels du compte ; sans accents ni casse). Indisponible sur des numéros\nmasqués.", "required": false, "schema": {"type": ["string", "null"]}}], "responses": {"200": {"description": "Appels, du plus récent au plus ancien", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Journal"}}}}, "403": {"description": "`interdit` (permission `journal.lire` sur le client, ou sur le poste demandé pour son titulaire ; `journal.voir_numeros` pour les numéros en entier)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`journal_invalide` : sens, issue, durée minimale, poste, limite ou recherche invalide (recherche indisponible sur des numéros masqués)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/appels-bloques": {"get": {"tags": ["clients"], "summary": "Appels entrants bloqués du client.", "operationId": "lireAppelsBloques", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Blocages", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AppelsBloques"}}}}, "403": {"description": "`interdit` (permission `client.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["clients"], "summary": "Remplace les appels entrants bloqués du client ; ses routes entrantes sont réécrites.", "operationId": "reglerAppelsBloques", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/AppelsBloques"}}}, "required": true}, "responses": {"200": {"description": "Blocages en place", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AppelsBloques"}}}}, "403": {"description": "`interdit` (permission `restriction.gerer`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`blocage_invalide` : numéro illisible, nom trop long, plus de 500 numéros", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/appels-chiffres": {"get": {"tags": ["clients"], "summary": "Appels chiffrés du client.", "operationId": "lireAppelsChiffres", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Réglage", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AppelsChiffres"}}}}, "403": {"description": "`interdit` (permission `reglages.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas un client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["clients"], "summary": "Active ou coupe les appels chiffrés du client.", "operationId": "reglerAppelsChiffres", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/AppelsChiffres"}}}, "required": true}, "responses": {"200": {"description": "Réglage", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AppelsChiffres"}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas un client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/appels.csv": {"get": {"tags": ["journal"], "summary": "Export CSV des appels du client, du plus ancien au plus récent.", "operationId": "exporterAppels", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "du", "in": "query", "description": "Début de la période (RFC 3339), inclus.", "required": false, "schema": {"type": ["string", "null"], "format": "date-time"}}, {"name": "au", "in": "query", "description": "Fin de la période (RFC 3339), exclue.", "required": false, "schema": {"type": ["string", "null"], "format": "date-time"}}, {"name": "sens", "in": "query", "description": "`entrant`, `sortant` ou `interne`.", "required": false, "schema": {"type": ["string", "null"]}}, {"name": "poste", "in": "query", "description": "Appels d'un poste ; le titulaire du poste voit les siens.", "required": false, "schema": {"type": ["string", "null"]}}, {"name": "limite", "in": "query", "description": "Appels par page (100 par défaut, 500 au plus).", "required": false, "schema": {"type": ["integer", "null"], "format": "int64"}}, {"name": "avant", "in": "query", "description": "Page suivante : `suivant` de la page précédente.", "required": false, "schema": {"type": ["string", "null"], "format": "date-time"}}, {"name": "numeros", "in": "query", "description": "`complets` : numéros en entier (permission `journal.voir_numeros`, tracé).", "required": false, "schema": {"type": ["string", "null"]}}, {"name": "repondu", "in": "query", "description": "Vrai : appels répondus (un entrant mis en relation avec une personne, D66) ; faux : appels\nmanqués (ni mis en relation ni message) et sortants sans réponse.", "required": false, "schema": {"type": ["boolean", "null"]}}, {"name": "issue", "in": "query", "description": "Issue (D66) : `repondu`, `manque` ou `message` (entrant), `sans_reponse` (sortant ou\ninterne non décroché).", "required": false, "schema": {"type": ["string", "null"]}}, {"name": "duree_min", "in": "query", "description": "Durée minimale, en secondes décrochées.", "required": false, "schema": {"type": ["integer", "null"], "format": "int32"}}, {"name": "mois", "in": "query", "description": "Mois `AAAA-MM` à l'heure de Paris (export du parc) : remplace `du` et `au`, comme la\nconsommation.", "required": false, "schema": {"type": ["string", "null"]}}, {"name": "recherche", "in": "query", "description": "Recherche (100 caractères au plus) : un numéro, même partiel, saisi en national (`06…`),\nen `00…` ou en `+33…`, un poste, ou le nom d'un contact (poste, répertoire commun,\ncontacts personnels du compte ; sans accents ni casse). Indisponible sur des numéros\nmasqués.", "required": false, "schema": {"type": ["string", "null"]}}], "responses": {"200": {"description": "CSV dans la langue de l'appelant (français : `;` et virgule décimale ; anglais : `,` et point), heures au fuseau du client, montants HT selon le rôle", "content": {"text/csv": {"schema": {"type": "string"}}}}, "403": {"description": "`interdit` (permission `journal.lire`, ou `journal.voir_numeros` pour les numéros en entier)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`journal_invalide` : sens, issue, durée minimale ou recherche invalide (recherche indisponible sur des numéros masqués), plus de 200 000 appels", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/appels/statistiques": {"get": {"tags": ["journal"], "summary": "Statistiques des appels reçus : jour par jour par issue, et carte de la semaine heure par\nheure.", "operationId": "statistiquesAppels", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "jours", "in": "query", "description": "Jours couverts, jusqu'à aujourd'hui compris (30 par défaut, 90 au plus).", "required": false, "schema": {"type": ["integer", "null"], "format": "int64"}}], "responses": {"200": {"description": "Statistiques de la période", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/StatistiquesClient"}}}}, "403": {"description": "`interdit` (permission `journal.lire` sur le client)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`periode_invalide`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/appels/synthese": {"get": {"tags": ["journal"], "summary": "Chiffres du journal d'appels sur une période (tous les appels, pas une page).", "operationId": "syntheseAppels", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "du", "in": "query", "description": "Début de la période (RFC 3339), inclus.", "required": false, "schema": {"type": ["string", "null"], "format": "date-time"}}, {"name": "au", "in": "query", "description": "Fin de la période (RFC 3339), exclue.", "required": false, "schema": {"type": ["string", "null"], "format": "date-time"}}, {"name": "poste", "in": "query", "description": "Appels d'un poste ; le titulaire du poste voit les siens.", "required": false, "schema": {"type": ["string", "null"]}}], "responses": {"200": {"description": "Chiffres de la période", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SyntheseAppels"}}}}, "403": {"description": "`interdit` (permission `journal.lire` sur le client, ou sur le poste demandé pour son titulaire)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/appels/{id}/trace": {"get": {"tags": ["diagnostic"], "summary": "Trace d'un appel du journal (diagnostic) : chemin dans le dialplan, applications, fin.", "operationId": "tracerAppel", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "id", "in": "path", "description": "Appel", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Trace", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/TraceAppel"}}}}, "403": {"description": "`interdit` (permission `diagnostic.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : appel", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/boites": {"get": {"tags": ["messagerie"], "summary": "Boîtes vocales des postes du client.", "operationId": "listerBoites", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Boîtes, par numéro de poste", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/BoiteVocale"}}}}}, "403": {"description": "`interdit` (permission `messagerie.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`messagerie_desactivee` : messagerie vocale coupée par l'opérateur (D94)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/boites/{poste}": {"get": {"tags": ["messagerie"], "summary": "Une boîte vocale.", "operationId": "lireBoite", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "poste", "in": "path", "description": "Numéro du poste", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "La boîte", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BoiteVocale"}}}}, "403": {"description": "`interdit` (permission `messagerie.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client ou poste ; `boite_absente` : poste sans boîte vocale", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`messagerie_desactivee` : messagerie vocale coupée par l'opérateur (D94)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["messagerie"], "summary": "Règle une boîte vocale.", "operationId": "reglerBoite", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "poste", "in": "path", "description": "Numéro du poste", "required": true, "schema": {"type": "string"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReglagesBoite"}}}, "required": true}, "responses": {"200": {"description": "La boîte réglée", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BoiteVocale"}}}}, "403": {"description": "`interdit` (permission `messagerie.regler`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client ou poste ; `boite_absente` : poste sans boîte vocale", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`messagerie_desactivee` : messagerie vocale coupée par l'opérateur (D94)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`boite_invalide` : adresse invalide, plus de 5 adresses, ou message non gardé sans e-mail en pièce jointe", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "post": {"tags": ["messagerie"], "summary": "Crée la boîte vocale d'un poste qui n'en a pas.", "description": "Poste signalé par `boite_absente` à la lecture. La boîte est réglée comme celle d'un nouveau\nposte : active, sans code, message gardé, sans e-mail ni transcription.", "operationId": "creerBoite", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "poste", "in": "path", "description": "Numéro du poste", "required": true, "schema": {"type": "string"}}], "responses": {"201": {"description": "La boîte créée", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BoiteVocale"}}}}, "403": {"description": "`interdit` (permission `messagerie.regler`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client ou poste", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`messagerie_desactivee` : messagerie vocale coupée par l'opérateur (D94) ; `boite_existante` : le poste a déjà sa boîte vocale", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/boites/{poste}/annonce": {"get": {"tags": ["messagerie"], "summary": "Écoute de l'annonce d'accueil de la boîte.", "operationId": "ecouterAnnonceBoite", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "poste", "in": "path", "description": "Numéro du poste", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "WAV mono 16 bits 8 kHz", "content": {"audio/wav": {"schema": {"type": "array", "items": {"type": "integer", "format": "int32", "minimum": 0}}}}}, "403": {"description": "`interdit` (permission `messagerie.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client, poste ou annonce ; `boite_absente` : poste sans boîte vocale", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`messagerie_desactivee` : messagerie vocale coupée par l'opérateur (D94)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["messagerie"], "summary": "Dépose l'annonce d'accueil de la boîte (D56) : le fichier (WAV, MP3, AAC/M4A, Ogg Vorbis,\nFLAC ; 20 Mo, 10 minutes au plus) est converti en WAV mono 16 bits 8 kHz. Un texte lu par une\nvoix passe par `POST /synthese`, puis ce dépôt.", "operationId": "deposerAnnonceBoite", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "poste", "in": "path", "description": "Numéro du poste", "required": true, "schema": {"type": "string"}}, {"name": "format", "in": "query", "description": "Extension du fichier d'origine (`mp3`, `m4a`…) : aide à reconnaître le format.", "required": false, "schema": {"type": ["string", "null"]}}, {"name": "texte", "in": "query", "description": "Texte lu par la voix de synthèse (`POST /synthese`) dont le fichier est le résultat,\ngardé pour le modifier plus tard (1500 caractères au plus) ; absent : le texte gardé est\noublié.", "required": false, "schema": {"type": ["string", "null"]}}], "requestBody": {"description": "Fichier audio", "content": {"application/octet-stream": {"schema": {"type": "array", "items": {"type": "integer", "format": "int32", "minimum": 0}}}}, "required": true}, "responses": {"200": {"description": "Annonce en place", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BoiteVocale"}}}}, "403": {"description": "`interdit` (permission `messagerie.regler`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client ou poste ; `boite_absente` : poste sans boîte vocale", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`messagerie_desactivee` : messagerie vocale coupée par l'opérateur (D94)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "413": {"description": "`annonce_trop_grosse` : plus de 20 Mo", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`audio_illisible` (format non reconnu), `audio_vide`, `audio_trop_long` (plus de 10 minutes)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "delete": {"tags": ["messagerie"], "summary": "Retire l'annonce d'accueil : l'annonce par défaut reprend.", "operationId": "retirerAnnonceBoite", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "poste", "in": "path", "description": "Numéro du poste", "required": true, "schema": {"type": "string"}}], "responses": {"204": {"description": "Annonce retirée"}, "403": {"description": "`interdit` (permission `messagerie.regler`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client, poste ou annonce ; `boite_absente` : poste sans boîte vocale", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`messagerie_desactivee` : messagerie vocale coupée par l'opérateur (D94)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/boites/{poste}/messages": {"get": {"tags": ["messagerie"], "summary": "Messages de la boîte, du plus récent au plus ancien.", "operationId": "listerMessages", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "poste", "in": "path", "description": "Numéro du poste", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "Messages ; numéro masqué et sans transcription sans la permission `messagerie.ecouter`", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/MessageVocal"}}}}}, "403": {"description": "`interdit` (permission `messagerie.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client ou poste ; `boite_absente` : poste sans boîte vocale", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`messagerie_desactivee` : messagerie vocale coupée par l'opérateur (D94)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/boites/{poste}/messages/{message}": {"get": {"tags": ["messagerie"], "summary": "Écoute d'un message : le fichier tel que déposé.", "operationId": "ecouterMessage", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "poste", "in": "path", "description": "Numéro du poste", "required": true, "schema": {"type": "string"}}, {"name": "message", "in": "path", "description": "Message", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "WAV, ou MP3 pour un message enregistré par le moteur de téléphonie", "content": {"audio/wav": {"schema": {"type": "array", "items": {"type": "integer", "format": "int32", "minimum": 0}}}}}, "403": {"description": "`interdit` (permission `messagerie.ecouter`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client, poste, message ou fichier ; `boite_absente` : poste sans boîte vocale", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`messagerie_desactivee` : messagerie vocale coupée par l'opérateur (D94)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["messagerie"], "summary": "Marque un message lu ou nouveau ; le voyant des téléphones suit.", "operationId": "marquerMessage", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "poste", "in": "path", "description": "Numéro du poste", "required": true, "schema": {"type": "string"}}, {"name": "message", "in": "path", "description": "Message", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/StatutMessage"}}}, "required": true}, "responses": {"204": {"description": "Statut changé"}, "403": {"description": "`interdit` (permission `messagerie.ecouter`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client, poste ou message ; `boite_absente` : poste sans boîte vocale", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`messagerie_desactivee` : messagerie vocale coupée par l'opérateur (D94)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "delete": {"tags": ["messagerie"], "summary": "Supprime un message (base et fichier) ; le voyant des téléphones suit.", "operationId": "supprimerMessage", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "poste", "in": "path", "description": "Numéro du poste", "required": true, "schema": {"type": "string"}}, {"name": "message", "in": "path", "description": "Message", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"204": {"description": "Message supprimé"}, "403": {"description": "`interdit` (permission `messagerie.ecouter`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client, poste ou message ; `boite_absente` : poste sans boîte vocale", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`messagerie_desactivee` : messagerie vocale coupée par l'opérateur (D94)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/budget": {"get": {"tags": ["journal"], "summary": "Budget mensuel d'un client : montant, consommation du mois au prix de vente au client et\nrestriction en cours (D116).", "operationId": "lireBudget", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Budget du client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BudgetClient"}}}}, "403": {"description": "`interdit` (permission `reglages.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["journal"], "summary": "Règle le budget mensuel d'un client : montant (absent : pas de budget) et blocage au seuil.\nRepart d'une feuille blanche pour le mois : une levée manuelle est oubliée, et le budget est\naussitôt réévalué (un budget abaissé sous la consommation restreint, s'il bloque).", "operationId": "reglerBudget", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReglageBudget"}}}, "required": true}, "responses": {"200": {"description": "Budget du client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BudgetClient"}}}}, "403": {"description": "`interdit` (permission `client.modifier` : admin du client, opérateur, revendeur du client)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`budget_invalide`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/budget/levee": {"post": {"tags": ["journal"], "summary": "Lève la restriction posée par le budget jusqu'à la fin du mois (admin du client, opérateur,\nrevendeur du client). Le plafond anti-piratage (D106) n'est pas touché.", "operationId": "leverBudget", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Budget du client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BudgetClient"}}}}, "403": {"description": "`interdit` (permission `client.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`pas_de_limitation`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/capture": {"get": {"tags": ["diagnostic"], "summary": "Capture en direct des journaux et de la trace SIP d'un client, en `text/event-stream` :\névénements `ligne` (JSON : nature `sip` ou `journal`, niveau, texte), puis `fin`. Cinq\nminutes au plus ; fermer la connexion arrête la capture. Journalisée.", "operationId": "capturerClient", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "duree", "in": "query", "description": "Durée en secondes (300 au plus, et par défaut).", "required": false, "schema": {"type": ["integer", "null"], "format": "int64", "minimum": 0}}], "responses": {"200": {"description": "Flux d'événements (`ligne`, `fin`)", "content": {"text/event-stream": {"schema": {"$ref": "#/components/schemas/LigneCapturee"}}}}, "403": {"description": "`interdit` (permission `diagnostic.agir`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas un client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/capture/pcap": {"post": {"tags": ["diagnostic"], "summary": "Fichier pcap (Wireshark) des messages SIP d'une capture : en-têtes IP, UDP et TCP\nreconstruits autour de chaque message. Rien n'est conservé sur le serveur.", "operationId": "exporterCapturePcap", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/DemandePcap"}}}, "required": true}, "responses": {"200": {"description": "Fichier pcap", "content": {"application/vnd.tcpdump.pcap": {"schema": {"type": "array", "items": {"type": "integer", "format": "int32", "minimum": 0}}}}}, "403": {"description": "`interdit` (permission `diagnostic.agir`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "413": {"description": "`capture_trop_grosse` : plus de 64 Mo de messages", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`capture_invalide` : messages ou adresses illisibles", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/enregistrements": {"get": {"tags": ["enregistrements"], "summary": "Enregistrements d'appels du client, du plus récent au plus ancien.", "operationId": "listerEnregistrements", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "du", "in": "query", "description": "Début de la période (RFC 3339), inclus.", "required": false, "schema": {"type": ["string", "null"], "format": "date-time"}}, {"name": "au", "in": "query", "description": "Fin de la période (RFC 3339), exclue.", "required": false, "schema": {"type": ["string", "null"], "format": "date-time"}}, {"name": "poste", "in": "query", "description": "Enregistrements d'un poste ; le titulaire du poste voit les siens.", "required": false, "schema": {"type": ["string", "null"]}}, {"name": "q", "in": "query", "description": "Numéro cherché parmi l'appelant et l'appelé (chiffres, comme la production).", "required": false, "schema": {"type": ["string", "null"]}}, {"name": "limite", "in": "query", "description": "Au plus (100 par défaut, 500 au plus).", "required": false, "schema": {"type": ["integer", "null"], "format": "int64"}}, {"name": "ids", "in": "query", "description": "Export : identifiants choisis (séparés par des virgules), à la place des filtres.", "required": false, "schema": {"type": ["string", "null"]}}], "responses": {"200": {"description": "Enregistrements", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/EnregistrementAppel"}}}}}, "403": {"description": "`interdit` (permission `enregistrement.ecouter` sur le client, ou sur le poste demandé pour son titulaire), `enregistrement_non_autorise` (option coupée pour ce client, D111)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`enregistrement_invalide` : limite invalide", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/enregistrements.zip": {"get": {"tags": ["enregistrements"], "summary": "Export ZIP des enregistrements choisis ou filtrés (admin du client) : un dossier par poste,\nheure du client dans les noms, 500 fichiers et 1,5 Gio au plus (production). Écrit en flux,\ntaille annoncée d'avance.", "operationId": "exporterEnregistrements", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "du", "in": "query", "description": "Début de la période (RFC 3339), inclus.", "required": false, "schema": {"type": ["string", "null"], "format": "date-time"}}, {"name": "au", "in": "query", "description": "Fin de la période (RFC 3339), exclue.", "required": false, "schema": {"type": ["string", "null"], "format": "date-time"}}, {"name": "poste", "in": "query", "description": "Enregistrements d'un poste ; le titulaire du poste voit les siens.", "required": false, "schema": {"type": ["string", "null"]}}, {"name": "q", "in": "query", "description": "Numéro cherché parmi l'appelant et l'appelé (chiffres, comme la production).", "required": false, "schema": {"type": ["string", "null"]}}, {"name": "limite", "in": "query", "description": "Au plus (100 par défaut, 500 au plus).", "required": false, "schema": {"type": ["integer", "null"], "format": "int64"}}, {"name": "ids", "in": "query", "description": "Export : identifiants choisis (séparés par des virgules), à la place des filtres.", "required": false, "schema": {"type": ["string", "null"]}}], "responses": {"200": {"description": "Archive ZIP (stockée)", "content": {"application/zip": {"schema": {"type": "array", "items": {"type": "integer", "format": "int32", "minimum": 0}}}}}, "403": {"description": "`interdit` (permission `enregistrement.ecouter` sur tout le client), `enregistrement_non_autorise` (option coupée pour ce client, D111)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "413": {"description": "`archive_trop_grosse` : plus de 500 fichiers ou de 1,5 Gio", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/enregistrements/{id}": {"get": {"tags": ["enregistrements"], "summary": "Écoute d'un enregistrement, par plages (`Range`) pour avancer dans l'audio.", "operationId": "ecouterEnregistrement", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "id", "in": "path", "description": "Appel", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "telecharger", "in": "query", "description": "Vrai : en pièce jointe (téléchargement), sinon lu dans le navigateur.", "required": false, "schema": {"type": "boolean"}}], "responses": {"200": {"description": "MP3 ou WAV", "content": {"audio/mpeg": {"schema": {"type": "array", "items": {"type": "integer", "format": "int32", "minimum": 0}}}}}, "206": {"description": "Plage demandée", "content": {"audio/mpeg": {"schema": {"type": "array", "items": {"type": "integer", "format": "int32", "minimum": 0}}}}}, "403": {"description": "`interdit` (permission `enregistrement.ecouter`), `enregistrement_non_autorise` (option coupée pour ce client, D111)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : enregistrement ou fichier", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "416": {"description": "`plage_invalide`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "delete": {"tags": ["enregistrements"], "summary": "Supprime un enregistrement (le fichier) ; l'appel reste au journal et à la facturation.\nAdmin du client seulement.", "operationId": "supprimerEnregistrement", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "id", "in": "path", "description": "Appel", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"204": {"description": "Enregistrement supprimé"}, "403": {"description": "`interdit` (permission `enregistrement.ecouter` sur tout le client), `enregistrement_non_autorise` (option coupée pour ce client, D111)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/evenements": {"get": {"tags": ["clients"], "summary": "Changements en direct d'un client, en `text/event-stream` : événements `changement` (JSON),\nune heure au plus, puis le navigateur se reconnecte. Le portail relit alors l'état des postes\nou des appels, sans interroger le moteur de téléphonie à intervalles.", "operationId": "evenementsDuClient", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Flux d'événements (`changement`)", "content": {"text/event-stream": {"schema": {"$ref": "#/components/schemas/Changement"}}}}, "403": {"description": "`interdit` (permission `poste.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas un client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "503": {"description": "`moteur_injoignable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/forfaits": {"get": {"tags": ["grilles"], "summary": "Forfaits indicatifs d'un client (D120) : celui de sa grille et le sien, vente au revendeur et\nvente au client. Le client lui-même ne les lit pas.", "operationId": "lireForfaits", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Forfaits du client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ForfaitsClient"}}}}, "403": {"description": "`interdit` (permission `grille.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas un client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/forfaits/{niveau}": {"put": {"tags": ["grilles"], "summary": "Règle le forfait indicatif d'un client à un niveau de vente, à la place de celui de sa grille\n(D120) ; sans forfait : celui de la grille reprend. Vente au client : l'opérateur ou le\nrevendeur du client ; vente au revendeur : l'opérateur seul. Au journal d'audit.", "operationId": "reglerForfait", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "niveau", "in": "path", "description": "Niveau de vente", "required": true, "schema": {"type": "string", "description": "Niveau de vente d'un forfait.", "enum": ["vente_revendeur", "vente_client"]}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReglageForfait"}}}, "required": true}, "responses": {"200": {"description": "Forfaits du client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ForfaitsClient"}}}}, "403": {"description": "`interdit` (permission `grille.gerer` sur le client, ou sur l'opérateur pour la vente au revendeur)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas un client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`forfait_invalide` : montant hors de 0 à 100 000 dans la devise de l'instance, ou vente au revendeur d'un client direct", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/horaires": {"get": {"tags": ["parcours"], "summary": "Grilles horaires du parcours publié : ouvertes ou fermées maintenant, jusqu'à quand.", "operationId": "etatHoraires", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Grilles du parcours publié (aucune sans parcours publié)", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/EtatHoraires"}}}}}, "403": {"description": "`interdit` (permission `parcours.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/journal": {"get": {"tags": ["journal"], "summary": "Réglage du journal du client.", "operationId": "lireReglageJournal", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Réglage", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReglageJournal"}}}}, "403": {"description": "`interdit` (permission `reglages.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["journal"], "summary": "Règle le journal du client : masquage des numéros externes (D60).", "operationId": "reglerJournal", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReglageJournal"}}}, "required": true}, "responses": {"200": {"description": "Réglage", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReglageJournal"}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/materiel/modeles": {"get": {"tags": ["materiel"], "summary": "Modèles qu'on peut ajouter aux postes du client, par profil (livrés, puis copies de\nl'opérateur).", "operationId": "listerModelesMateriel", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Modèles", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/ModeleDisponible"}}}}}, "403": {"description": "`interdit` (permission `poste.provisionner` sur le client)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/materiel/parametres": {"get": {"tags": ["materiel"], "summary": "Paramètres supplémentaires des téléphones du client, empilés entre ceux du profil et ceux de\nl'appareil.", "operationId": "lireParametresMaterielClient", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Paramètres", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ParametresMateriel"}}}}, "403": {"description": "`interdit` (permission `poste.provisionner` sur le client)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas un client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["materiel"], "summary": "Remplace les paramètres supplémentaires du client (opérateur et revendeur seulement).", "operationId": "reglerParametresMaterielClient", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/ParametresMateriel"}}}, "required": true}, "responses": {"200": {"description": "Paramètres", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ParametresMateriel"}}}}, "403": {"description": "`interdit` (permission `poste.provisionner` sur le client, et compte de l'opérateur ou d'un revendeur ; jamais par l'assistant ni le MCP)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas un client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`parametres_invalides` : ligne illisible (le détail la numérote)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/musique-attente": {"get": {"tags": ["parcours"], "summary": "Écoute de la musique d'attente du client.", "operationId": "ecouterMusiqueAttente", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "WAV mono 16 bits 8 kHz", "content": {"audio/wav": {"schema": {"type": "array", "items": {"type": "integer", "format": "int32", "minimum": 0}}}}}, "403": {"description": "`interdit` (permission `parcours.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas de musique propre (la générique est jouée)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["parcours"], "summary": "Dépose la musique d'attente du client : le fichier (WAV, MP3, AAC/M4A, Ogg Vorbis, FLAC ;\n20 Mo, 10 minutes au plus) est converti en WAV mono 16 bits 8 kHz et joué en boucle, depuis\nle début, à chaque mise en attente sur ses postes.", "operationId": "deposerMusiqueAttente", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "format", "in": "query", "description": "Extension du fichier d'origine (`mp3`, `m4a`…) : aide à reconnaître le format.", "required": false, "schema": {"type": ["string", "null"]}}, {"name": "texte", "in": "query", "description": "Texte lu par la voix de synthèse (`POST /synthese`) dont le fichier est le résultat,\ngardé pour le modifier plus tard (1500 caractères au plus) ; absent : le texte gardé est\noublié.", "required": false, "schema": {"type": ["string", "null"]}}], "requestBody": {"description": "Fichier audio", "content": {"application/octet-stream": {"schema": {"type": "array", "items": {"type": "integer", "format": "int32", "minimum": 0}}}}, "required": true}, "responses": {"204": {"description": "Musique en place sur tous les postes"}, "403": {"description": "`interdit` (permission `parcours.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "413": {"description": "`annonce_trop_grosse` : plus de 20 Mo", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`audio_illisible` (format non reconnu), `audio_vide`, `audio_trop_long` (plus de 10 minutes)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "delete": {"tags": ["parcours"], "summary": "Retire la musique d'attente du client : la musique générique reprend.", "operationId": "retirerMusiqueAttente", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"204": {"description": "Musique retirée"}, "403": {"description": "`interdit` (permission `parcours.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/numeros": {"get": {"tags": ["numeros"], "summary": "Numéros d'un client.", "operationId": "listerNumerosClient", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Numéros du client", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/Numero"}}}}}, "403": {"description": "`interdit` (permission `numero.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "post": {"tags": ["numeros"], "summary": "Affecte un numéro libre du stock à un client. Un numéro réservé ne va qu'à un client du\nrevendeur ; un revendeur n'affecte que ses réservés (D40).", "operationId": "affecterNumero", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/Affectation"}}}, "required": true}, "responses": {"200": {"description": "Numéro affecté", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Numero"}}}}, "403": {"description": "`interdit` (permission `numero.affecter`, ou numéro non réservé au revendeur)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`numero_indisponible` : pas libre", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`reservation_autre_revendeur`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/numeros/{numero_id}": {"delete": {"tags": ["numeros"], "summary": "Retire un numéro à un client : il redevient libre dans le stock, avec sa réservation, sort\ndu parcours (nouvelle version publiée) et n'est plus routé.", "operationId": "retirerNumero", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "numero_id", "in": "path", "description": "Numéro", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Numéro rendu au stock", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Numero"}}}}, "403": {"description": "`interdit` (permission `numero.affecter`, ou numéro non réservé au revendeur)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas un numéro de ce client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`numero_deja_route` : un numéro du client est routé dans un autre domaine", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`parcours_invalide` : le parcours publié ne se publie plus", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/numeros/{numero_id}/destination": {"put": {"tags": ["numeros"], "summary": "Règle la destination d'un numéro du client : un de ses postes, ou aucune. Raccourci du\nparcours : publie une nouvelle version (le brouillon qui partait de la version servie reçoit\nle même changement), et la route entrante est réécrite aussitôt.", "operationId": "routerNumero", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "numero_id", "in": "path", "description": "Numéro", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/Destination"}}}, "required": true}, "responses": {"200": {"description": "Numéro routé", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Numero"}}}}, "403": {"description": "`interdit` (permission `numero.router`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas un numéro de ce client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`numero_deja_route` : un numéro du client est routé dans un autre domaine", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`poste_inconnu` ; `parcours_invalide` : le parcours publié ne se publie plus", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/parcours": {"get": {"tags": ["parcours"], "summary": "Le parcours du client : version servie, et brouillon avec sa vérification.", "operationId": "lireParcours", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Version publiée et brouillon", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/EtatParcours"}}}}, "403": {"description": "`interdit` (permission `parcours.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/parcours/brouillon": {"put": {"tags": ["parcours"], "summary": "Enregistre le brouillon du client (il remplace le précédent).", "operationId": "enregistrerBrouillon", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/NouveauBrouillon"}}}, "required": true}, "responses": {"200": {"description": "Brouillon enregistré, avec sa vérification", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Brouillon"}}}}, "403": {"description": "`interdit` (permission `parcours.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client, ou version de base inconnue", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "delete": {"tags": ["parcours"], "summary": "Abandonne le brouillon du client.", "operationId": "abandonnerBrouillon", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"204": {"description": "Brouillon abandonné"}, "403": {"description": "`interdit` (permission `parcours.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client ou brouillon", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/parcours/connecteurs-sip/{ext}/mot-de-passe": {"put": {"tags": ["parcours"], "summary": "Enregistre le mot de passe du connecteur SIP de numéro interne `ext`, chiffré (D27), hors du\nparcours. Si la version publiée contient ce connecteur, sa passerelle est mise à jour tout\nde suite (arrêt puis rechargement), sans nouvelle version : un connecteur écarté faute de mot\nde passe entre en service. Tracé, sans le mot de passe.", "operationId": "definirMotDePasseConnecteurSip", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "ext", "in": "path", "description": "Numéro interne du connecteur", "required": true, "schema": {"type": "string"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/MotDePasseConnecteur"}}}, "required": true}, "responses": {"204": {"description": "Mot de passe enregistré"}, "403": {"description": "`interdit` (permission `parcours.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`numero_deja_route`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`ext_invalide` ; `mot_de_passe_invalide` : 1 à 128 caractères ASCII imprimables, sans espace ni `\"'<>&\\`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/parcours/disposition": {"get": {"tags": ["parcours"], "summary": "Disposition du schéma du parcours du client.", "operationId": "lireDisposition", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Modules posés à la main (vide : tout est automatique)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Disposition"}}}}, "403": {"description": "`interdit` (permission `parcours.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["parcours"], "summary": "Remplace la disposition du schéma (vide : tout redevient automatique, « Réorganiser »).", "operationId": "enregistrerDisposition", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/Disposition"}}}, "required": true}, "responses": {"200": {"description": "Disposition enregistrée", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Disposition"}}}}, "403": {"description": "`interdit` (permission `parcours.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`disposition_invalide` : plus de 500 modules, identifiant ou coordonnée hors bornes", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/parcours/publication": {"post": {"tags": ["parcours"], "summary": "Publie le brouillon du client : il devient la version servie, et disparaît. Les modules\nécartés par la validation gardent ce qui était servi.", "operationId": "publierParcours", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/DemandePublication"}}}, "required": true}, "responses": {"201": {"description": "Nouvelle version servie", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Publication"}}}}, "403": {"description": "`interdit` (permission `parcours.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client ou brouillon", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`parcours_modifie` : une version a été publiée depuis le début du brouillon ; `numero_deja_route` : un numéro est routé dans un autre domaine", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`parcours_invalide` : erreur qui empêche toute publication (identifiant en double, lien vers un module inconnu)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/parcours/rejouer": {"post": {"tags": ["diagnostic"], "summary": "Rejoue la publication du parcours d'un client : sa dernière version est réécrite dans le\nmoteur de téléphonie, sans nouvelle version ; tracé.", "operationId": "rejouerParcours", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"204": {"description": "Parcours réécrit (rien sans version publiée)"}, "403": {"description": "`interdit` (permission `diagnostic.agir`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`numero_deja_route`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/parcours/verification": {"post": {"tags": ["parcours"], "summary": "Vérifie un parcours sans l'enregistrer : validation face aux postes et numéros du client, et\nchangements par rapport à la version publiée.", "operationId": "verifierParcours", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/Parcours"}}}, "required": true}, "responses": {"200": {"description": "Validation et changements", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Verification"}}}}, "403": {"description": "`interdit` (permission `parcours.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/parcours/versions": {"get": {"tags": ["parcours"], "summary": "Versions publiées du client, de la plus récente à la plus ancienne.", "operationId": "listerVersionsParcours", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Versions, sans leur contenu", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/ResumeVersion"}}}}}, "403": {"description": "`interdit` (permission `parcours.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/parcours/versions/{version}": {"get": {"tags": ["parcours"], "summary": "Une version publiée, avec son contenu.", "operationId": "lireVersionParcours", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "version", "in": "path", "description": "Numéro de version", "required": true, "schema": {"type": "integer", "format": "int32"}}], "responses": {"200": {"description": "La version", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/VersionParcours"}}}}, "403": {"description": "`interdit` (permission `parcours.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : version", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/parcours/versions/{version}/restauration": {"post": {"tags": ["parcours"], "summary": "Reprend une version publiée dans le brouillon (il remplace le brouillon en cours), à\npublier ensuite.", "operationId": "restaurerVersionParcours", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "version", "in": "path", "description": "Numéro de version", "required": true, "schema": {"type": "integer", "format": "int32"}}], "responses": {"200": {"description": "Brouillon repris de la version", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Brouillon"}}}}, "403": {"description": "`interdit` (permission `parcours.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client ou version", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/plafond": {"get": {"tags": ["trunks"], "summary": "Plafond de consommation d'un client : seuils, consommation et limitation en cours.", "operationId": "lirePlafond", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Plafond du client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PlafondClient"}}}}, "403": {"description": "`interdit` (permission `client.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["trunks"], "summary": "Règle les seuils propres à un client (absents : ceux de l'instance) ; admin opérateur seul.", "operationId": "reglerPlafondClient", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/SeuilsDuClient"}}}, "required": true}, "responses": {"200": {"description": "Plafond du client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PlafondClient"}}}}, "403": {"description": "`interdit` (admin opérateur seul)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`plafond_invalide`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/plafond/levee": {"post": {"tags": ["trunks"], "summary": "Lève la restriction d'un client : au niveau de l'heure, par l'admin du client ou l'opérateur ;\nau niveau du jour, par l'opérateur seul. Le comptage de la fenêtre repart de zéro.", "operationId": "leverPlafond", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Plafond du client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PlafondClient"}}}}, "403": {"description": "`interdit` (permission `reglages.modifier` ; au niveau du jour, admin opérateur seul)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`pas_de_limitation`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/postes/etat": {"get": {"tags": ["clients"], "summary": "État des postes d'un client : inscrits maintenant, appareils, dernière inscription.", "operationId": "etatDesPostes", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "État de chaque poste", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/EtatPoste"}}}}}, "403": {"description": "`interdit` (permission `poste.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas un client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "503": {"description": "`moteur_injoignable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/postes/{poste}/enregistrement": {"get": {"tags": ["clients"], "summary": "Réglage d'enregistrement du poste.", "operationId": "lireEnregistrementPoste", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "poste", "in": "path", "description": "Numéro du poste", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "Réglage", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Enregistrement"}}}}, "403": {"description": "`interdit` (permission `utilisateur.lire`), `enregistrement_non_autorise` (option coupée pour ce client, D111)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client ou poste", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["clients"], "summary": "Règle l'enregistrement des appels du poste ; le parcours publié est réécrit (armement avant\nun prédécroché).", "operationId": "reglerEnregistrementPoste", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "poste", "in": "path", "description": "Numéro du poste", "required": true, "schema": {"type": "string"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/Enregistrement"}}}, "required": true}, "responses": {"200": {"description": "Réglage", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Enregistrement"}}}}, "403": {"description": "`interdit` (permission `utilisateur.modifier`), `enregistrement_non_autorise` (option coupée pour ce client, D111)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client ou poste", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`numero_deja_route` : le parcours réécrit route un numéro déjà routé ailleurs", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`parcours_invalide` : le parcours publié ne se réécrit pas", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/postes/{poste}/informations-sip": {"get": {"tags": ["provisionnement"], "summary": "Informations SIP du poste, pour le configurer à la main (identifiant, serveur et domaine,\nproxy sortant au besoin, ports) ; le mot de passe se demande avec `revelerMotDePasseSip`.", "operationId": "lireInformationsSip", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "poste", "in": "path", "description": "Numéro du poste", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "Informations SIP, sans le mot de passe", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/InformationsSip"}}}}, "403": {"description": "`interdit` (permission `poste.provisionner`, sur le client ou pour le titulaire du poste)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client ou poste", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/postes/{poste}/informations-sip/mot-de-passe": {"post": {"tags": ["provisionnement"], "summary": "Révèle le mot de passe SIP du poste (D114), pour configurer un téléphone à la main : à qui peut\ninstaller le poste, en personne ou par une clé d'API, jamais par l'assistant ni le MCP. Chaque\nrévélation est au journal d'audit (sans le mot de passe). `POST` et `Cache-Control: no-store`\npour qu'aucun cache ni préchargement ne le garde.", "operationId": "revelerMotDePasseSip", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "poste", "in": "path", "description": "Numéro du poste", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "Mot de passe SIP du poste", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MotDePasseSip"}}}}, "403": {"description": "`interdit` (permission `poste.provisionner`, sur le client ou pour le titulaire du poste ; jamais par l'assistant ni le MCP)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client ou poste", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/postes/{poste}/installation": {"post": {"tags": ["provisionnement"], "summary": "Envoie par e-mail le lien de la page d'installation du téléphone (valable sept jours), par\nle serveur SMTP de l'opérateur. La page choisit l'application selon l'appareil.", "operationId": "envoyerInstallation", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "poste", "in": "path", "description": "Numéro du poste", "required": true, "schema": {"type": "string"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/DemandeInstallation"}}}, "required": true}, "responses": {"200": {"description": "Lien envoyé", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/InstallationEnvoyee"}}}}, "403": {"description": "`interdit` (permission `poste.provisionner`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client ou poste, ou poste désactivé", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`smtp_absent` : aucun serveur d'e-mails réglé par l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`courriel_invalide` : adresse invalide, ou aucune adresse (poste sans titulaire)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "502": {"description": "`smtp_echec` : le serveur a refusé ou n'a pas répondu (détail du serveur)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/postes/{poste}/mobile/acces": {"get": {"tags": ["provisionnement"], "summary": "Applications mobiles maison activées sur ce poste (D117), sans leurs jetons.", "operationId": "listerAccesMobiles", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "poste", "in": "path", "description": "Numéro du poste", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "Accès en cours, du plus récent au plus ancien", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/AccesMobile"}}}}}, "403": {"description": "`interdit` (permission `poste.provisionner`, sur le client ou pour le titulaire du poste)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client ou poste", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/postes/{poste}/mobile/acces/{id}": {"delete": {"tags": ["provisionnement"], "summary": "Révoque une application mobile maison activée sur ce poste (D117) : son jeton d'appareil\ncesse de valoir et son inscription push est oubliée.", "operationId": "revoquerAccesMobile", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "poste", "in": "path", "description": "Numéro du poste", "required": true, "schema": {"type": "string"}}, {"name": "id", "in": "path", "description": "Accès", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"204": {"description": "Accès révoqué"}, "403": {"description": "`interdit` (permission `poste.provisionner`, sur le client ou pour le titulaire du poste)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client, poste ou accès", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/postes/{poste}/mobile/installation": {"post": {"tags": ["provisionnement"], "summary": "QR code d'installation de l'application mobile maison sur ce poste (D117) : un lien signé,\nvalable un jour, que l'application échange une seule fois contre un jeton d'appareil au nom\ndu titulaire du poste. À qui peut installer le poste (`poste.provisionner`).", "operationId": "installerAppliMobile", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "poste", "in": "path", "description": "Numéro du poste", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "Lien d'installation (réponse jamais mise en cache)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/InstallationMobile"}}}}, "403": {"description": "`interdit` (permission `poste.provisionner`, sur le client ou pour le titulaire du poste)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client ou poste, ou poste désactivé", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`appli_mobile_desactivee`, ou `sans_titulaire` : le poste n'a pas de compte titulaire", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/postes/{poste}/mobiles": {"get": {"tags": ["provisionnement"], "summary": "Applications mobiles inscrites sur un poste (sans leur jeton push) : à qui peut installer le\nposte (permission `poste.provisionner`).", "operationId": "listerMobiles", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "poste", "in": "path", "description": "Numéro du poste", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "Appareils mobiles du poste", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/AppareilMobile"}}}}}, "403": {"description": "`interdit` (permission `poste.provisionner`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client ou poste", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/postes/{poste}/mobiles/{id}": {"delete": {"tags": ["provisionnement"], "summary": "Retire une application mobile d'un poste (téléphone perdu, départ du collaborateur) : elle\nn'est plus réveillée.", "operationId": "retirerMobile", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "poste", "in": "path", "description": "Numéro du poste", "required": true, "schema": {"type": "string"}}, {"name": "id", "in": "path", "description": "Appareil mobile", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"204": {"description": "Appareil retiré"}, "403": {"description": "`interdit` (permission `poste.provisionner`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client, poste ou appareil", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/postes/{poste}/mot-de-passe-sip": {"post": {"tags": ["provisionnement"], "summary": "Renouvelle le mot de passe SIP du poste (D41), par exemple après la perte d'un téléphone : les\ntéléphones installés ne s'inscrivent plus, et tous les liens d'installation déjà émis sont\nrévoqués (leur signature dépend du mot de passe). Réinstaller ensuite les téléphones du poste\navec un lien neuf. Le mot de passe n'est jamais renvoyé.", "operationId": "renouvelerMotDePasseSip", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "poste", "in": "path", "description": "Numéro du poste", "required": true, "schema": {"type": "string"}}], "responses": {"204": {"description": "Mot de passe renouvelé"}, "403": {"description": "`interdit` (permission `poste.provisionner`, sur le client ou pour le titulaire du poste)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client ou poste", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/postes/{poste}/ne-pas-deranger": {"get": {"tags": ["clients"], "summary": "« Ne pas déranger » du poste.", "operationId": "lireNePasDeranger", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "poste", "in": "path", "description": "Numéro du poste", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "État", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/NePasDeranger"}}}}, "403": {"description": "`interdit` (permission `renvoi.lire`, sur le client ou pour le titulaire du poste)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client ou poste", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["clients"], "summary": "Règle « ne pas déranger » du poste, appliqué à l'appel suivant.", "operationId": "reglerNePasDeranger", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "poste", "in": "path", "description": "Numéro du poste", "required": true, "schema": {"type": "string"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/NePasDeranger"}}}, "required": true}, "responses": {"200": {"description": "État", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/NePasDeranger"}}}}, "403": {"description": "`interdit` (permission `renvoi.regler`, sur le client ou pour le titulaire du poste)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client ou poste", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/postes/{poste}/numero-presente": {"put": {"tags": ["numeros"], "summary": "Choisit le numéro qu'un poste présente à l'extérieur, parmi les numéros du client (comme en\nproduction).", "operationId": "choisirNumeroPresente", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "poste", "in": "path", "description": "Numéro du poste", "required": true, "schema": {"type": "string"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/ChoixNumeroPresente"}}}, "required": true}, "responses": {"200": {"description": "Numéro présenté du poste", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/NumeroPresente"}}}}, "403": {"description": "`interdit` (permission `numero.router`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client, poste ou numéro de ce client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/postes/{poste}/provisionnement": {"post": {"tags": ["provisionnement"], "summary": "Liens d'installation d'un téléphone mobile sur ce poste. Ils portent le mot de passe SIP : à\nne montrer qu'à son titulaire.", "operationId": "provisionnerPoste", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "poste", "in": "path", "description": "Numéro du poste", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "Liens d'installation", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/LiensPoste"}}}}, "403": {"description": "`interdit` (permission `poste.provisionner`, sur le client ou pour le titulaire du poste)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client ou poste, ou poste désactivé", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/postes/{poste}/renvois": {"get": {"tags": ["clients"], "summary": "Renvois du poste.", "operationId": "lireRenvois", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "poste", "in": "path", "description": "Numéro du poste", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "Renvois", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/RenvoisPoste"}}}}, "403": {"description": "`interdit` (permission `renvoi.lire`, sur le client ou pour le titulaire du poste)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client ou poste", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["clients"], "summary": "Règle les renvois du poste, appliqués à l'appel suivant (sans publier le parcours).", "operationId": "reglerRenvois", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "poste", "in": "path", "description": "Numéro du poste", "required": true, "schema": {"type": "string"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/RenvoisPoste"}}}, "required": true}, "responses": {"200": {"description": "Renvois", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/RenvoisPoste"}}}}, "403": {"description": "`interdit` (permission `renvoi.regler`, sur le client ou pour le titulaire du poste)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client ou poste", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`renvoi_invalide` : numéro qui n'est pas un fixe ou un mobile du pays du client (numéro spécial, autre pays), renvoi actif sans numéro", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/postes/{poste}/restrictions": {"get": {"tags": ["trunks"], "summary": "Restrictions d'appel d'un poste : pour qui voit les postes du client, et pour son titulaire,\nqui les lit dans « Mon poste » sans pouvoir les changer.", "operationId": "lireRestrictionsPoste", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "poste", "in": "path", "description": "Numéro du poste", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "Restrictions du poste (vide : aucune)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/RestrictionsPoste"}}}}, "403": {"description": "`interdit` (permission `poste.lire`, ou titulaire du poste)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["trunks"], "summary": "Remplace les restrictions d'un poste. Les urgences restent toujours joignables (D22).", "operationId": "restreindrePoste", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "poste", "in": "path", "description": "Numéro du poste", "required": true, "schema": {"type": "string"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/NouvellesRestrictions"}}}, "required": true}, "responses": {"200": {"description": "Restrictions du poste", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/RestrictionsPoste"}}}}, "403": {"description": "`interdit` (permission `restriction.gerer`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas un client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`nature_invalide`, `poste_inconnu`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/repertoire": {"get": {"tags": ["repertoire"], "summary": "Répertoire commun du client, par nom.", "operationId": "listerRepertoire", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Contacts", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/ContactRepertoire"}}}}}, "403": {"description": "`interdit` (permission `repertoire.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "post": {"tags": ["repertoire"], "summary": "Ajoute un contact au répertoire commun.", "operationId": "ajouterContact", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/SaisieContact"}}}, "required": true}, "responses": {"201": {"description": "Contact ajouté", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ContactRepertoire"}}}}, "403": {"description": "`interdit` (permission `repertoire.gerer`, ou collaborateur du client en personne) ; `repertoire_ferme` : le client ne l'ouvre pas à ses collaborateurs", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`contact_invalide` : nom vide ou trop long, numéro non externe", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/repertoire-ouvert": {"get": {"tags": ["repertoire"], "summary": "Le répertoire commun du client est-il ouvert à ses collaborateurs ?", "operationId": "lireRepertoireOuvert", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Réglage", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/RepertoireOuvert"}}}}, "403": {"description": "`interdit` (permission `reglages.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["repertoire"], "summary": "Ouvre ou ferme le répertoire commun aux collaborateurs du client.", "operationId": "reglerRepertoireOuvert", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/RepertoireOuvert"}}}, "required": true}, "responses": {"200": {"description": "Réglage", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/RepertoireOuvert"}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/repertoire/{id}": {"put": {"tags": ["repertoire"], "summary": "Modifie un contact du répertoire commun.", "operationId": "modifierContact", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "id", "in": "path", "description": "Contact", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/SaisieContact"}}}, "required": true}, "responses": {"200": {"description": "Contact modifié", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ContactRepertoire"}}}}, "403": {"description": "`interdit` (permission `repertoire.gerer`, ou l'auteur du contact) ; `repertoire_ferme`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client ou contact", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`contact_invalide` : nom vide ou trop long, numéro non externe", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "delete": {"tags": ["repertoire"], "summary": "Retire un contact du répertoire commun.", "operationId": "supprimerContact", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "id", "in": "path", "description": "Contact", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"204": {"description": "Contact retiré"}, "403": {"description": "`interdit` (permission `repertoire.gerer`, ou l'auteur du contact) ; `repertoire_ferme`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : client ou contact", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/restrictions": {"get": {"tags": ["trunks"], "summary": "Restrictions d'appel des postes d'un client.", "operationId": "listerRestrictions", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Postes restreints", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/RestrictionsPoste"}}}}}, "403": {"description": "`interdit` (permission `poste.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/revalorisation": {"post": {"tags": ["grilles"], "summary": "Recalcule les prix des appels sortants du client sur la période, d'après les grilles en\nvigueur le jour de chaque appel : aperçu de l'écart, puis application.", "operationId": "revaloriserClient", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/DemandeRevalorisation"}}}, "required": true}, "responses": {"200": {"description": "Aperçu, ou bilan si appliqué", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ApercuRevalorisation"}}}}, "403": {"description": "`interdit` (admin opérateur seul)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`revalorisation_invalide` : jour invalide, fin de période avant son début", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/securite": {"get": {"tags": ["clients"], "summary": "Sécurité d'un client.", "operationId": "lireSecuriteClient", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Réglage", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SecuriteClient"}}}}, "403": {"description": "`interdit` (permission `reglages.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas un client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["clients"], "summary": "Impose (ou non) le second facteur aux utilisateurs simples du client.", "operationId": "reglerSecuriteClient", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/SecuriteClient"}}}, "required": true}, "responses": {"200": {"description": "Réglage", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SecuriteClient"}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas un client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/sso": {"get": {"tags": ["reglages"], "summary": "Choix du client pour la connexion par le portail de l'opérateur.", "operationId": "lireSsoClient", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Réglage", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReglageSsoClient"}}}}, "403": {"description": "`interdit` (permission `reglages.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["reglages"], "summary": "Règle le choix du client : créer ou non le compte d'une adresse inconnue à sa première\nconnexion par le portail de l'opérateur.", "operationId": "reglerSsoClient", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReglageSsoClient"}}}, "required": true}, "responses": {"200": {"description": "Réglage enregistré", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReglageSsoClient"}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas un client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/synthese": {"post": {"tags": ["parcours"], "summary": "Lit un texte avec la voix choisie par le client (`…/voix`), sinon celle de l'instance réglée\npar l'opérateur (Piper, ou Google avec Piper en secours), et renvoie le WAV tel que le\ntéléphone le jouera ; rien n'est stocké. Pour en faire une annonce, déposer ce WAV\n(`PUT …/annonces/…`).", "operationId": "synthetiser", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/Texte"}}}, "required": true}, "responses": {"200": {"description": "WAV mono 16 bits 8 kHz", "content": {"audio/wav": {"schema": {"type": "array", "items": {"type": "integer", "format": "int32", "minimum": 0}}}}}, "403": {"description": "`interdit` (permission `parcours.modifier`, ou `messagerie.regler` sur le poste donné)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`texte_invalide` : vide ou plus de 1500 caractères", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "500": {"description": "`synthese_echouee`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "503": {"description": "Lecture par Piper (moteur choisi, ou secours de Google) : `synthese_indisponible` (Piper non installé), `synthese_anglaise_indisponible` (client réglé en anglais, voix anglaise non installée), `synthese_occupee`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/tarifs": {"get": {"tags": ["grilles"], "summary": "Tarifs du client : sa grille de vente (attribuée, sinon celle par défaut de son revendeur ou\nde l'opérateur), en lecture seule.", "operationId": "lireTarifs", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Tarifs du client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/TarifsClient"}}}}, "403": {"description": "`interdit` (permission `client.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas un client, ou aucune grille de vente", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/trunk": {"get": {"tags": ["trunks"], "summary": "Le trunk C5 d'un client.", "operationId": "lireTrunk", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Trunk, sans son mot de passe", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Trunk"}}}}, "403": {"description": "`interdit` (permission `trunk.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas de trunk", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["trunks"], "summary": "Crée ou remplace le trunk C5 d'un client : sa passerelle, ses routes sortantes et les\nréseaux de son fournisseur.", "operationId": "enregistrerTrunk", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/NouveauTrunk"}}}, "required": true}, "responses": {"200": {"description": "Trunk, sans son mot de passe", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Trunk"}}}}, "403": {"description": "`interdit` (permission `trunk.gerer`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas un client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`numero_deja_route` : le NDI a changé et le parcours, réécrit, route un numéro déjà routé ailleurs", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`profil_inconnu`, `proxy_invalide` (absent ou invalide sans profil), `identifiant_invalide`, `mot_de_passe_requis`, `format_invalide` (absent ou invalide sans profil), `reseau_invalide`, `ndi_inconnu` (pas un numéro du client), `parcours_invalide` (le NDI a changé et le parcours publié ne se réécrit plus)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "delete": {"tags": ["trunks"], "summary": "Supprime le trunk d'un client : sa passerelle et ses routes sortantes. Le client ne peut\nplus appeler l'extérieur.", "operationId": "supprimerTrunk", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"204": {"description": "Trunk supprimé"}, "403": {"description": "`interdit` (permission `trunk.gerer`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas de trunk", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`numero_deja_route` : le parcours, réécrit sans NDI, route un numéro déjà routé ailleurs", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`parcours_invalide` : le parcours publié, réécrit sans NDI, ne se réécrit plus", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/trunk/reenregistrer": {"post": {"tags": ["diagnostic"], "summary": "Force le réenregistrement du trunk d'un client auprès de son fournisseur (`killgw` puis\n`rescan`) ; tracé.", "operationId": "reenregistrerTrunk", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"204": {"description": "Trunk relancé"}, "403": {"description": "`interdit` (permission `diagnostic.agir`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas de trunk", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/utilisateurs": {"get": {"tags": ["clients"], "summary": "Utilisateurs d'un client, avec leur poste.", "operationId": "listerUtilisateurs", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Utilisateurs", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/UtilisateurClient"}}}}}, "403": {"description": "`interdit` (permission `utilisateur.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "post": {"tags": ["clients"], "summary": "Crée un utilisateur chez un client, avec son poste s'il en a un, et lui envoie son\ninvitation par e-mail (serveur SMTP de l'opérateur). L'opérateur et le revendeur du client\najoutent toujours ; l'admin du client, seulement si l'opérateur ou le revendeur le lui laisse\n(D121 : chaque compte compte dans la licence et dans ce que l'opérateur facture).", "operationId": "creerUtilisateur", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/NouvelUtilisateur"}}}, "required": true}, "responses": {"201": {"description": "Utilisateur (et poste) créés", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UtilisateurClient"}}}}, "403": {"description": "`interdit` (permissions `utilisateur.creer`, `poste.creer`) ; `ajout_utilisateurs_non_autorise` : compte du client alors que l'opérateur ne lui laisse pas l'ajout (D121) ; `licence_bloquee` : licence échue depuis plus de 30 jours (D78)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas un client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`courriel_pris`, `poste_existant`, `numero_de_module` (numéro interne d'un module du parcours)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`nom_invalide`, `courriel_invalide`, `role_invalide`, `poste_invalide`, `poste_numero_urgence`, `telephone_seulement_invalide` (un admin ne peut pas être limité au téléphone)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/voix": {"get": {"tags": ["clients"], "summary": "La voix des annonces du client : son choix, la voix de l'instance et celle qui lit.", "operationId": "lireVoixClient", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Voix du client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/VoixDuClient"}}}}, "403": {"description": "`interdit` (permission `reglages.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas un client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["clients"], "summary": "Choisit la voix des annonces du client, parmi celles de l'instance pour sa langue, ou revient\nà la voix de l'instance. Les annonces déjà enregistrées ne changent pas : la voix sert aux\nprochains textes lus.", "operationId": "reglerVoixClient", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/NouvelleVoixClient"}}}, "required": true}, "responses": {"200": {"description": "Voix enregistrée", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/VoixDuClient"}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas un client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`voix_indisponible` : voix que l'instance n'offre pas ; `voix_autre_langue` : voix d'une autre langue que celle du client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/voix/disponibles": {"get": {"tags": ["clients"], "summary": "Voix que le client peut choisir : celles de l'instance pour la langue de ses annonces, la\nvoix de l'instance en tête.", "operationId": "listerVoix", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Voix disponibles (vide si l'instance n'en a aucune pour cette langue)", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/VoixSynthese"}}}}}, "403": {"description": "`interdit` (permission `reglages.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas un client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/clients/{client_id}/voix/essai": {"post": {"tags": ["clients"], "summary": "Fait lire une courte phrase dans la langue du client par une voix, pour l'écouter avant de\nla choisir ; rien n'est enregistré. Comme pour une annonce, Piper lit si Google échoue.", "operationId": "ecouterVoix", "parameters": [{"name": "client_id", "in": "path", "description": "Client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/EssaiVoixClient"}}}, "required": true}, "responses": {"200": {"description": "WAV mono 16 bits 8 kHz", "content": {"audio/wav": {"schema": {"type": "array", "items": {"type": "integer", "format": "int32", "minimum": 0}}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas un client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`voix_indisponible` : voix que l'instance n'offre pas ; `voix_autre_langue` : voix d'une autre langue que celle du client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "500": {"description": "`synthese_echouee`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "503": {"description": "`synthese_indisponible` (aucune voix installée), `synthese_anglaise_indisponible` (client réglé en anglais, sans voix anglaise), `synthese_occupee`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/connexion": {"post": {"tags": ["connexion"], "summary": "Ouvre une session. Le jeton est posé dans un cookie `HttpOnly`, `Secure`, `SameSite=Strict`.\nUn cookie `appareil` valide pour ce compte (appareil de confiance, D53) dispense du\nsecond facteur : l'étape est alors `connecte`. Sur un appareil de confiance, la session dure\njusqu'à la fin de la confiance (30 jours au plus, D76).", "operationId": "seConnecter", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/Identifiants"}}}, "required": true}, "responses": {"200": {"description": "Mot de passe vérifié ; session à l'étape indiquée (cookie `session`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/EtatConnexion"}}}}, "401": {"description": "`identifiants_invalides` : compte inconnu, inactif, bloqué ou mot de passe faux", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "429": {"description": "`trop_de_requetes` : trop de tentatives depuis cette adresse (en-tête `Retry-After`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}}}, "/api/v1/connexion/passkey/debut": {"post": {"tags": ["connexion"], "summary": "Commence la connexion par passkey (session en attente du second facteur) : options à passer\nà `navigator.credentials.get()`.", "operationId": "commencerConnexionPasskey", "responses": {"200": {"description": "Options WebAuthn d'authentification (`publicKey`)", "content": {"application/json": {"schema": {}}}}, "409": {"description": "`aucune_passkey`, `etape_de_connexion_invalide`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}}}, "/api/v1/connexion/passkey/fin": {"post": {"tags": ["connexion"], "summary": "Termine la connexion par passkey : session complète (nouveau cookie). Un refus compte comme\nun échec de connexion (blocage après 5).", "operationId": "terminerConnexionPasskey", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/FinAuthentification"}}}, "required": true}, "responses": {"200": {"description": "Connecté", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/EtatConnexion"}}}}, "400": {"description": "`pas_de_ceremonie`, `passkey_refusee`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "401": {"description": "`passkey_refusee` : signature refusée ou compte bloqué", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "429": {"description": "`trop_de_requetes` : trop de tentatives depuis cette adresse (en-tête `Retry-After`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}}}, "/api/v1/connexion/second-facteur": {"post": {"tags": ["connexion"], "summary": "Termine la connexion par un code TOTP ou un code de secours. Cinq codes faux bloquent le\ncompte 15 minutes, comme les mots de passe faux. Avec `confiance`, ce navigateur est dispensé\ndu code pendant 30 jours (le mot de passe reste demandé).", "operationId": "validerSecondFacteur", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/CodeDeConnexion"}}}, "required": true}, "responses": {"200": {"description": "Connecté : nouvelle session complète (nouveau cookie ; avec `confiance`, aussi `appareil`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/EtatConnexion"}}}}, "401": {"description": "`code_invalide` ou `non_connecte`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`etape_de_connexion_invalide` : la session n'attend pas de second facteur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "429": {"description": "`trop_de_requetes` : trop de tentatives depuis cette adresse (en-tête `Retry-After`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}}}, "/api/v1/deconnexion": {"post": {"tags": ["connexion"], "summary": "Ferme la session courante.", "operationId": "seDeconnecter", "responses": {"204": {"description": "Session fermée, cookie effacé"}}}}, "/api/v1/deconnexion/partout": {"post": {"tags": ["connexion"], "summary": "Déconnecte le compte de tous ses appareils : ferme toutes ses sessions, la courante comprise,\net oublie ses appareils de confiance (mot de passe et code redemandés partout, D76).", "operationId": "seDeconnecterPartout", "responses": {"204": {"description": "Sessions fermées, cookies effacés"}, "401": {"description": "`non_connecte`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "403": {"description": "`interdit` : appel par clé d'API", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/fuseaux": {"get": {"tags": ["reglages"], "summary": "Fuseaux proposés (noms IANA, triés).", "operationId": "listerFuseaux", "responses": {"200": {"description": "Noms IANA", "content": {"application/json": {"schema": {"type": "array", "items": {"type": "string"}}}}}}, "security": [{"session": []}]}}, "/api/v1/grilles/{id}": {"get": {"tags": ["grilles"], "summary": "Une grille et ses lignes.", "operationId": "lireGrille", "parameters": [{"name": "id", "in": "path", "description": "Grille", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "La grille", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/GrilleTarifaireDetaillee"}}}}, "403": {"description": "`interdit` (permission `grille.lire` sur son propriétaire)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "delete": {"tags": ["grilles"], "summary": "Supprime une grille ; les CDR déjà valorisés gardent leurs montants (D13).", "operationId": "supprimerGrille", "parameters": [{"name": "id", "in": "path", "description": "Grille", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"204": {"description": "Grille supprimée, et ses attributions"}, "403": {"description": "`interdit` (permission `grille.gerer` sur son propriétaire)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/grilles/{id}/defaut": {"put": {"tags": ["grilles"], "summary": "Fait de la grille celle par défaut de son propriétaire, pour sa nature.", "operationId": "grilleParDefaut", "parameters": [{"name": "id", "in": "path", "description": "Grille", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Grille par défaut", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/GrilleTarifaire"}}}}, "403": {"description": "`interdit` (permission `grille.gerer` sur son propriétaire)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/grilles/{id}/forfait": {"put": {"tags": ["grilles"], "summary": "Règle le forfait indicatif par défaut d'une grille de vente (D120) : par utilisateur ou\nglobal, pour la marge des clients qui n'ont pas le leur ; sans forfait : aucun.", "operationId": "reglerForfaitGrille", "parameters": [{"name": "id", "in": "path", "description": "Grille", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReglageForfait"}}}, "required": true}, "responses": {"200": {"description": "La grille et son forfait", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/GrilleTarifaire"}}}}, "403": {"description": "`interdit` (permission `grille.gerer` sur son propriétaire)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`forfait_invalide` : grille d'achat, ou montant hors de 0 à 100 000 dans la devise de l'instance", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/marque": {"get": {"tags": ["exploitation"], "summary": "Marque de l'opérateur : nom, couleurs, logo. Sans session.", "operationId": "lireMarque", "responses": {"200": {"description": "Marque", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Marque"}}}}}}}, "/api/v1/marque/icone": {"get": {"tags": ["exploitation"], "summary": "Icône carrée de l'application (favicon, application installée) : celle déposée (PNG), sinon\nl'initiale du nom de l'opérateur, en blanc sur sa couleur (zone sûre des icônes masquables\nrespectée). Sans session.", "operationId": "lireIcone", "responses": {"200": {"description": "PNG déposé, sinon SVG généré", "content": {"image/svg+xml": {"schema": {"type": "string"}}}}}}}, "/api/v1/marque/logo": {"get": {"tags": ["exploitation"], "summary": "Logo de l'opérateur. Sans session ; mis en cache par le navigateur (l'adresse change avec\nlui).", "operationId": "lireLogo", "responses": {"200": {"description": "PNG, JPEG ou WebP", "content": {"image/png": {"schema": {"type": "array", "items": {"type": "integer", "format": "int32", "minimum": 0}}}}}, "404": {"description": "`introuvable` : aucun logo", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}}}, "/api/v1/marque/manifeste": {"get": {"tags": ["exploitation"], "summary": "Manifeste du portail installable (PWA) : nom et couleur de l'opérateur, icône à sa couleur.\nSans session.", "operationId": "lireManifeste", "responses": {"200": {"description": "Manifeste", "content": {"application/manifest+json": {"schema": {"type": "object"}}}}}}}, "/api/v1/marque/manifeste-telephone": {"get": {"tags": ["exploitation"], "summary": "Manifeste du softphone installable (D107) : une application à part du portail (`id`, portée\net départ `/telephone/`), « Téléphone » à la marque de l'opérateur, qui ouvre les liens\n`tel:` et `sip:`. Sans session ; nom en anglais si le navigateur le préfère.", "operationId": "lireManifesteTelephone", "responses": {"200": {"description": "Manifeste", "content": {"application/manifest+json": {"schema": {"type": "object"}}}}}}}, "/api/v1/materiel/apercu": {"post": {"tags": ["materiel"], "summary": "Fichiers qu'un profil produit pour un appareil fictif du modèle choisi (données fictives,\nmots de passe masqués) ; un gabarit en erreur donne son message et sa position.", "operationId": "apercuMateriel", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/DemandeApercu"}}}, "required": true}, "responses": {"200": {"description": "Aperçu", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ApercuMateriel"}}}}, "403": {"description": "`interdit` (équipe de l'opérateur ou admin d'un revendeur)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : profil", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`profil_materiel_invalide` : ni profil ni contenu, ou modèle absent du profil", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/materiel/profils": {"get": {"tags": ["materiel"], "summary": "Profils de matériel : ceux que Kanadr livre et les copies de l'opérateur.", "operationId": "listerProfilsMateriel", "responses": {"200": {"description": "Profils", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProfilsMateriel"}}}}, "403": {"description": "`interdit` (équipe de l'opérateur ou admin d'un revendeur)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "post": {"tags": ["materiel"], "summary": "Copie un profil (livré ou déjà copié) pour le modifier : la copie garde son profil livré\nd'origine et sa version.", "operationId": "dupliquerProfilMateriel", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/DuplicationProfil"}}}, "required": true}, "responses": {"201": {"description": "Copie", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProfilMateriel"}}}}, "403": {"description": "`interdit` (admin de l'opérateur ; jamais par l'assistant ni le MCP)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : profil copié", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`profil_materiel_invalide` : nom vide ou trop long", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/materiel/profils/{reference}": {"get": {"tags": ["materiel"], "summary": "Un profil et son contenu (gabarits compris).", "operationId": "lireProfilMateriel", "parameters": [{"name": "reference", "in": "path", "description": "Identifiant d'un profil livré ou uuid d'une copie", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "Profil", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProfilMateriel"}}}}, "403": {"description": "`interdit` (équipe de l'opérateur ou admin d'un revendeur)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["materiel"], "summary": "Enregistre une nouvelle version d'une copie (les profils livrés ne se modifient pas : on les\ncopie). Gabarits compilés et paramètres vérifiés avant d'écrire.", "operationId": "modifierProfilMateriel", "parameters": [{"name": "reference", "in": "path", "description": "Copie de l'opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/ModificationProfil"}}}, "required": true}, "responses": {"200": {"description": "Profil", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProfilMateriel"}}}}, "403": {"description": "`interdit` (admin de l'opérateur ; jamais par l'assistant ni le MCP)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`profil_materiel_invalide` : nom, modèles, motifs, gabarit qui ne se compile pas, paramètres illisibles (le détail situe l'erreur)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "delete": {"tags": ["materiel"], "summary": "Supprime une copie qu'aucun appareil n'utilise.", "operationId": "supprimerProfilMateriel", "parameters": [{"name": "reference", "in": "path", "description": "Copie de l'opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"204": {"description": "Supprimée"}, "403": {"description": "`interdit` (admin de l'opérateur ; jamais par l'assistant ni le MCP)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`profil_materiel_utilise` : des appareils l'utilisent", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/materiel/profils/{reference}/differences": {"get": {"tags": ["materiel"], "summary": "Différences entre une copie et la version livrée actuelle de son profil d'origine, gabarit\npar gabarit.", "operationId": "differencesProfilMateriel", "parameters": [{"name": "reference", "in": "path", "description": "Copie de l'opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Différences", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/DifferencesProfil"}}}}, "403": {"description": "`interdit` (équipe de l'opérateur ou admin d'un revendeur)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : copie, ou profil d'origine qui n'est plus livré", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/materiel/profils/{reference}/versions": {"get": {"tags": ["materiel"], "summary": "Historique d'une copie, de la plus récente à la plus ancienne.", "operationId": "listerVersionsProfilMateriel", "parameters": [{"name": "reference", "in": "path", "description": "Copie de l'opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Versions", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/VersionProfil"}}}}}, "403": {"description": "`interdit` (équipe de l'opérateur ou admin d'un revendeur)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/materiel/profils/{reference}/versions/{version}/restaurer": {"post": {"tags": ["materiel"], "summary": "Restaure une version de l'historique : elle devient la version suivante.", "operationId": "restaurerVersionProfilMateriel", "parameters": [{"name": "reference", "in": "path", "description": "Copie de l'opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "version", "in": "path", "description": "Version restaurée", "required": true, "schema": {"type": "integer", "format": "int32", "minimum": 0}}], "responses": {"200": {"description": "Profil", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProfilMateriel"}}}}, "403": {"description": "`interdit` (admin de l'opérateur ; jamais par l'assistant ni le MCP)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : copie ou version", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/materiel/rps": {"get": {"tags": ["materiel"], "summary": "Clés RPS de l'opérateur, sans le secret.", "operationId": "lireRps", "responses": {"200": {"description": "Clés réglées", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReglageRps"}}}}, "403": {"description": "`interdit` (permission `reglages.lire` sur l'opérateur)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : aucune clé réglée", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["materiel"], "summary": "Enregistre les clés RPS de l'opérateur (YMCS › Integration › API) : le secret est chiffré et\njamais renvoyé ; absent, celui enregistré est gardé.", "operationId": "reglerRps", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/NouveauReglageRps"}}}, "required": true}, "responses": {"200": {"description": "Clés enregistrées", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReglageRps"}}}}, "403": {"description": "`interdit` (permission `reglages.modifier` sur l'opérateur ; jamais par l'assistant ni le MCP)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`rps_invalide` : identifiant, région, serveur ou secret manquants ou invalides", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "delete": {"tags": ["materiel"], "summary": "Retire les clés RPS (et leur secret).", "operationId": "retirerRps", "responses": {"204": {"description": "Retirées"}, "403": {"description": "`interdit` (permission `reglages.modifier` sur l'opérateur ; jamais par l'assistant ni le MCP)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : aucune clé réglée", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/materiel/rps/essai": {"post": {"tags": ["materiel"], "summary": "Essaie les clés : jeton YMCS, puis le serveur RPS nommé.", "operationId": "essayerRps", "responses": {"204": {"description": "Clés acceptées et serveur RPS trouvé"}, "403": {"description": "`interdit` (permission `reglages.modifier` sur l'opérateur)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : aucune clé réglée", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "502": {"description": "`rps_echec` : refus de YMCS (son message), ou serveur RPS introuvable", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/mise-en-route": {"get": {"tags": ["exploitation"], "summary": "État de la mise en route : étapes de l'assistant et constats. Admin opérateur.", "operationId": "lireMiseEnRoute", "responses": {"200": {"description": "Mise en route", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MiseEnRoute"}}}}, "403": {"description": "`interdit` (permission `reglages.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/mise-en-route/affichage": {"put": {"tags": ["exploitation"], "summary": "Masque ou réaffiche la tuile de la mise en route sur l'accueil de l'opérateur.", "operationId": "reglerAffichageMiseEnRoute", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/AffichageMiseEnRoute"}}}, "required": true}, "responses": {"200": {"description": "Mise en route", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MiseEnRoute"}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/mise-en-route/certificat": {"get": {"tags": ["exploitation"], "summary": "Certificat servi en HTTPS et dernière demande Let's Encrypt. Admin opérateur.", "operationId": "lireCertificat", "responses": {"200": {"description": "Certificat", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Certificat"}}}}, "403": {"description": "`interdit` (permission `reglages.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "post": {"tags": ["exploitation"], "summary": "Demande un certificat Let's Encrypt pour l'hôte de l'instance (`KANADR_URL_PUBLIQUE`), et\nseulement lui : le service système qui lance certbot relit l'hôte dans les réglages de la\nmachine ; rien ne vient de la requête. Le résultat se lit sur `GET /mise-en-route/certificat`.", "operationId": "demanderCertificat", "responses": {"202": {"description": "Demande transmise au service du certificat", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Certificat"}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`demande_en_cours` : une demande attend ou s'exécute", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`hote_non_public` : adresse publique sans `https://` ou sans nom de domaine", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "503": {"description": "`service_certificat_absent` : répertoire d'état inaccessible", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/mise-en-route/domaines": {"get": {"tags": ["exploitation"], "summary": "Ce que le DNS donne pour le nom d'hôte de l'instance, et pour un nom sous le suffixe des\ndomaines clients (enregistrement générique). Admin opérateur.", "operationId": "verifierDomainesMiseEnRoute", "responses": {"200": {"description": "Résolution du nom d'hôte", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Domaines"}}}}, "403": {"description": "`interdit` (permission `reglages.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/mise-en-route/etapes/{etape}": {"put": {"tags": ["exploitation"], "summary": "Règle l'état d'une étape : faite, passée ou de nouveau à faire.", "operationId": "reglerEtapeMiseEnRoute", "parameters": [{"name": "etape", "in": "path", "description": "Étape (`langue`, `identite`, `domaines`…)", "required": true, "schema": {"type": "string"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReglageEtape"}}}, "required": true}, "responses": {"200": {"description": "Mise en route", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MiseEnRoute"}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : étape inconnue", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`etat_etape_invalide` : état inconnu (ni à faire, ni fait, ni passé)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/mise-en-route/premier-acces": {"post": {"tags": ["exploitation"], "summary": "Premier accès : crée l'opérateur et son premier administrateur, comme `kanadr initialiser`.\nLe lien ne sert qu'une fois. Sans session.", "operationId": "premierAcces", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/PremierAcces"}}}, "required": true}, "responses": {"201": {"description": "Opérateur créé ; lien d'invitation de l'administrateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PremierAccesFait"}}}}, "404": {"description": "`introuvable` : lien inconnu, expiré ou déjà utilisé", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`nom_invalide`, `courriel_invalide`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}}}, "/api/v1/mise-en-route/premier-acces/verification": {"post": {"tags": ["exploitation"], "summary": "Le lien de premier accès est-il valable ? Sans session ; 404 sinon, comme toute adresse\ninconnue.", "operationId": "verifierPremierAcces", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/JetonMiseEnRoute"}}}, "required": true}, "responses": {"204": {"description": "Lien valable : l'instance attend son opérateur"}, "404": {"description": "`introuvable` : lien inconnu, expiré ou déjà utilisé", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}}}, "/api/v1/mobile/activation": {"post": {"tags": ["provisionnement"], "summary": "Activation de l'application mobile maison (D117), sans session : le jeton du QR code, valide\net jamais servi, contre un jeton d'appareil au nom du titulaire du poste. La configuration\nSIP se lit ensuite avec ce jeton (`GET /moi/telephone`).", "operationId": "activerAppliMobile", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/DemandeActivation"}}}, "required": true}, "responses": {"200": {"description": "Jeton d'appareil (réponse jamais mise en cache)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ActivationMobile"}}}}, "404": {"description": "`introuvable` : lien invalide, expiré, ou révoqué par un nouveau mot de passe SIP", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`lien_deja_utilise`, `appli_mobile_desactivee` ou `sans_titulaire`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`acces_mobile_invalide` : identifiant ou nom invalide", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}}}, "/api/v1/moi": {"get": {"tags": ["connexion"], "summary": "Compte de la session courante.", "operationId": "moi", "responses": {"200": {"description": "Compte connecté", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Moi"}}}}, "401": {"description": "`non_connecte`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/moi/accueil/{espace}": {"get": {"tags": ["compte"], "summary": "Disposition de l'accueil du compte connecté, dans un espace.", "operationId": "lireDispositionAccueil", "parameters": [{"name": "espace", "in": "path", "description": "`operateur` ou `client`", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "Disposition", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/DispositionAccueil"}}}}, "403": {"description": "`interdit` : appel par une clé d'API", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : espace inconnu", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["compte"], "summary": "Règle la disposition de l'accueil du compte connecté ; `instances` absent : retour à la\ndisposition par défaut. Tracé.", "operationId": "reglerDispositionAccueil", "parameters": [{"name": "espace", "in": "path", "description": "`operateur` ou `client`", "required": true, "schema": {"type": "string"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/DispositionAccueil"}}}, "required": true}, "responses": {"200": {"description": "Disposition enregistrée", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/DispositionAccueil"}}}}, "403": {"description": "`interdit` : appel par une clé d'API", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : espace inconnu", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`accueil_invalide` : identifiant mal formé, instance en double, ou plus de 30 modules", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/moi/applications": {"get": {"tags": ["oauth"], "summary": "Applications autorisées par le compte connecté (OAuth, serveur MCP), en vigueur.", "operationId": "listerApplicationsAutorisees", "responses": {"200": {"description": "Applications autorisées, les plus récentes d'abord", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/ApplicationAutorisee"}}}}}, "403": {"description": "`interdit` : appel par clé d'API, application autorisée, assistant ou MCP", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/moi/applications/{id}": {"delete": {"tags": ["oauth"], "summary": "Retire l'accès d'une application : ses jetons cessent aussitôt de valoir.", "operationId": "revoquerApplicationAutorisee", "parameters": [{"name": "id", "in": "path", "description": "Accord", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"204": {"description": "Accès retiré"}, "403": {"description": "`interdit` : appel par clé d'API, application autorisée, assistant ou MCP", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : accord inconnu, d'un autre compte ou déjà révoqué", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/moi/contacts": {"get": {"tags": ["connexion"], "summary": "Contacts personnels du compte connecté, par nom.", "operationId": "listerMesContacts", "responses": {"200": {"description": "Contacts personnels", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/ContactPersonnel"}}}}}, "401": {"description": "`non_connecte`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "403": {"description": "`interdit` : clé d'API, application autorisée, assistant ou MCP", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "post": {"tags": ["connexion"], "summary": "Ajoute un contact personnel.", "operationId": "ajouterMonContact", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/SaisieContactPersonnel"}}}, "required": true}, "responses": {"201": {"description": "Contact ajouté", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ContactPersonnel"}}}}, "403": {"description": "`interdit` : clé d'API, application autorisée, assistant ou MCP", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`trop_de_contacts` : 500 au plus", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`contact_invalide`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/moi/contacts/{id}": {"put": {"tags": ["connexion"], "summary": "Modifie un contact personnel.", "operationId": "modifierMonContact", "parameters": [{"name": "id", "in": "path", "description": "Contact", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/SaisieContactPersonnel"}}}, "required": true}, "responses": {"200": {"description": "Contact modifié", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ContactPersonnel"}}}}, "403": {"description": "`interdit` : clé d'API, application autorisée, assistant ou MCP", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`contact_invalide`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "delete": {"tags": ["connexion"], "summary": "Supprime un contact personnel, et son favori.", "operationId": "supprimerMonContact", "parameters": [{"name": "id", "in": "path", "description": "Contact", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"204": {"description": "Contact supprimé"}, "403": {"description": "`interdit` : clé d'API, application autorisée, assistant ou MCP", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/moi/favoris": {"get": {"tags": ["connexion"], "summary": "Favoris du compte connecté, dans l'ordre.", "operationId": "listerMesFavoris", "responses": {"200": {"description": "Favoris", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/Favori"}}}}}, "403": {"description": "`interdit` : clé d'API, application autorisée, assistant ou MCP", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["connexion"], "summary": "Remplace les favoris du compte connecté (liste ordonnée, 30 au plus, sans doublon) ; un\nfavori personnel désigne un de ses contacts personnels.", "operationId": "remplacerMesFavoris", "requestBody": {"content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/Favori"}}}}, "required": true}, "responses": {"200": {"description": "Favoris enregistrés", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/Favori"}}}}}, "403": {"description": "`interdit` : clé d'API, application autorisée, assistant ou MCP", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`favori_invalide` : plus de 30, doublon, référence vide ou contact personnel inconnu", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/moi/langue": {"put": {"tags": ["compte"], "summary": "Règle la langue du compte connecté (portail, e-mails qui lui sont adressés) ; absente, celle\nde son organisation. Tracé.", "operationId": "reglerLangueDuCompte", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/LangueDuCompte"}}}, "required": true}, "responses": {"200": {"description": "Langue du compte", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/LangueDuCompte"}}}}, "403": {"description": "`interdit` : appel par une clé d'API", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`langue_invalide` : ni français ni anglais", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/moi/telephone": {"get": {"tags": ["connexion"], "summary": "Identifiants SIP du poste du compte connecté, pour le softphone (D107) : à son seul\ntitulaire, connecté en personne (ni clé d'API, ni application autorisée, ni assistant, ni\nMCP), jamais à un admin pour le compte d'un autre. Lecture journalisée, sans le mot de passe.", "operationId": "lireMonTelephone", "responses": {"200": {"description": "Identifiants du poste et serveurs ICE (réponse jamais mise en cache)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MonTelephone"}}}}, "401": {"description": "`non_connecte`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "403": {"description": "`interdit` : clé d'API, application autorisée, assistant ou MCP", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`sans_poste` : le compte n'a pas de poste", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/moi/telephone/contacts": {"get": {"tags": ["connexion"], "summary": "Contacts du softphone : les autres postes en service du client du compte, puis son\nrépertoire commun.", "operationId": "contactsDeMonTelephone", "responses": {"200": {"description": "Contacts", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/ContactTelephone"}}}}}, "401": {"description": "`non_connecte`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "403": {"description": "`interdit` : clé d'API, application autorisée, assistant ou MCP", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`sans_poste` : le compte n'a pas de poste", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/moi/telephone/mobile": {"post": {"tags": ["connexion"], "summary": "Inscrit l'application mobile du compte connecté sur son poste (D117), ou rafraîchit son jeton\npush. Au titulaire du poste, en personne. Une nouvelle inscription met en place le réveil du\nposte.", "operationId": "inscrireMobile", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/InscriptionMobile"}}}, "required": true}, "responses": {"200": {"description": "Appareil inscrit", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AppareilMobile"}}}}, "401": {"description": "`non_connecte`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "403": {"description": "`interdit` : clé d'API, application autorisée, assistant ou MCP", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`sans_poste` : le compte n'a pas de poste", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`mobile_non_disponible` : passerelle de push non réglée", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`appareil_mobile_invalide`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/moi/telephone/mobile/acces": {"delete": {"tags": ["connexion"], "summary": "Déconnexion de l'application mobile maison (D117) : elle révoque son propre jeton d'appareil\net oublie son inscription push. Avec un jeton d'appareil seulement.", "operationId": "deconnecterAppliMobile", "responses": {"204": {"description": "Jeton révoqué"}, "401": {"description": "`non_connecte`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : appel sans jeton d'appareil", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/moi/telephone/mobile/{identifiant}": {"delete": {"tags": ["connexion"], "summary": "Retire l'application mobile du compte connecté (déconnexion de l'application) : elle n'est\nplus réveillée.", "operationId": "retirerMonMobile", "parameters": [{"name": "identifiant", "in": "path", "description": "Identifiant de l'installation", "required": true, "schema": {"type": "string"}}], "responses": {"204": {"description": "Appareil retiré"}, "401": {"description": "`non_connecte`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "403": {"description": "`interdit` : clé d'API, application autorisée, assistant ou MCP", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/mot-de-passe": {"post": {"tags": ["connexion"], "summary": "Définit le mot de passe avec un jeton d'invitation ou de réinitialisation. Ferme les\nsessions ouvertes du compte.", "operationId": "definirMotDePasse", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/NouveauMotDePasse"}}}, "required": true}, "responses": {"204": {"description": "Mot de passe défini"}, "400": {"description": "`jeton_invalide` : inconnu, expiré ou déjà utilisé", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`mot_de_passe_trop_court`, `mot_de_passe_trop_long`, `mot_de_passe_contient_courriel` ou `mot_de_passe_trop_courant`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "429": {"description": "`trop_de_requetes` : trop de tentatives depuis cette adresse (en-tête `Retry-After`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}}}, "/api/v1/mot-de-passe/oubli": {"post": {"tags": ["connexion"], "summary": "Mot de passe oublié : si un compte actif porte cette adresse et qu'un serveur d'e-mails est\nréglé, un lien pour choisir un nouveau mot de passe (valable une heure) part à cette adresse.\nLa réponse est la même dans tous les cas, et rendue avant l'envoi : elle ne dit pas si le\ncompte existe.", "operationId": "motDePasseOublie", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/DemandeOubli"}}}, "required": true}, "responses": {"202": {"description": "Demande prise en compte (e-mail envoyé si le compte existe)"}, "429": {"description": "`trop_de_requetes` : trop de demandes depuis cette adresse (en-tête `Retry-After`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}}}, "/api/v1/numeros/{numero_id}/etat": {"put": {"tags": ["numeros"], "summary": "Change l'état d'un numéro. Hors client : `libre`, `porte_sortant` ou `resilie`. Un numéro\nchez un client ne passe qu'à `porte_sortant` : il quitte le client comme un retrait (parcours\nrepublié, route supprimée, plus présenté) et ne se réaffecte pas.", "operationId": "changerEtatNumero", "parameters": [{"name": "numero_id", "in": "path", "description": "Numéro", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/ChangementEtat"}}}, "required": true}, "responses": {"200": {"description": "Numéro", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Numero"}}}}, "403": {"description": "`interdit` (permission `numero.gerer`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`numero_deja_route` : un numéro du client est routé dans un autre domaine", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`etat_invalide` ; `parcours_invalide` : le parcours publié ne se publie plus", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/numeros/{numero_id}/reservation": {"put": {"tags": ["numeros"], "summary": "Réserve un numéro du stock pour un revendeur, ou lève la réservation.", "operationId": "reserverNumero", "parameters": [{"name": "numero_id", "in": "path", "description": "Numéro", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/Reservation"}}}, "required": true}, "responses": {"200": {"description": "Numéro", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Numero"}}}}, "403": {"description": "`interdit` (permission `numero.gerer`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`revendeur_invalide`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/oauth/demandes/{id}": {"get": {"tags": ["oauth"], "summary": "Demande d'autorisation en attente de l'accord du compte connecté.", "operationId": "lireDemandeOauth", "parameters": [{"name": "id", "in": "path", "description": "Demande d'autorisation", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Application qui demande l'accès", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/DemandeOauth"}}}}, "403": {"description": "`interdit` : appel par clé d'API, application autorisée, assistant ou MCP", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : demande expirée ou déjà traitée", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/oauth/demandes/{id}/reponse": {"post": {"tags": ["oauth"], "summary": "Accorde ou refuse l'accès demandé ; l'accord est tracé au journal d'audit.", "operationId": "repondreDemandeOauth", "parameters": [{"name": "id", "in": "path", "description": "Demande d'autorisation", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReponseDemandeOauth"}}}, "required": true}, "responses": {"200": {"description": "Adresse où renvoyer le navigateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/RedirectionOauth"}}}}, "403": {"description": "`interdit` : appel par clé d'API, application autorisée, assistant ou MCP", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : demande expirée ou déjà traitée", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}": {"get": {"tags": ["organisations"], "summary": "Une organisation : nom, type, parent.", "operationId": "lireOrganisation", "parameters": [{"name": "id", "in": "path", "description": "Organisation", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Organisation", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/OrganisationLue"}}}}, "403": {"description": "`interdit` (permission `organisation.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/acrobits": {"get": {"tags": ["reglages"], "summary": "Le Cloud ID de l'application mobile de l'opérateur.", "operationId": "lireAcrobits", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Cloud ID réglé", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReglageAcrobits"}}}}, "403": {"description": "`interdit` (permission `reglages.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur, ou aucun Cloud ID réglé", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["reglages"], "summary": "Règle le Cloud ID de l'application mobile de l'opérateur : les liens CSC le portent. Le\nprovisionnement initial se règle chez Acrobits (`…/api/v1/provision/cloudsoftphone?p=%password%`).", "operationId": "reglerAcrobits", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReglageAcrobits"}}}, "required": true}, "responses": {"200": {"description": "Cloud ID réglé", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReglageAcrobits"}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`cloud_id_invalide` : 2 à 32 capitales, chiffres, tiret ou souligné", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "delete": {"tags": ["reglages"], "summary": "Retire le Cloud ID : plus de lien CSC (Acrobits Softphone reste possible).", "operationId": "retirerAcrobits", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"204": {"description": "Cloud ID retiré"}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/alertes": {"get": {"tags": ["reglages"], "summary": "Adresses qui reçoivent les alertes d'une organisation.", "operationId": "lireAlertes", "parameters": [{"name": "id", "in": "path", "description": "Opérateur ou revendeur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Adresses", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AdressesAlerte"}}}}, "403": {"description": "`interdit` (permission `reglages.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : ni l'opérateur ni un revendeur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["reglages"], "summary": "Règle les adresses d'alerte (dix au plus).", "operationId": "reglerAlertes", "parameters": [{"name": "id", "in": "path", "description": "Opérateur ou revendeur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/AdressesAlerte"}}}, "required": true}, "responses": {"200": {"description": "Adresses", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AdressesAlerte"}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : ni l'opérateur ni un revendeur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`courriel_invalide` : adresse invalide ou plus de dix", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/appels-en-cours": {"get": {"tags": ["diagnostic"], "summary": "Appels en cours chez les clients de l'organisation (diagnostic).", "operationId": "appelsEnCours", "parameters": [{"name": "id", "in": "path", "description": "Organisation (opérateur ou revendeur)", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Jambes en cours", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/AppelEnCours"}}}}}, "403": {"description": "`interdit` (permission `diagnostic.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "503": {"description": "`moteur_injoignable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/appels-en-cours/{uuid}": {"delete": {"tags": ["diagnostic"], "summary": "Coupe un appel en cours (une jambe) d'un client de l'organisation ; tracé.", "operationId": "couperAppel", "parameters": [{"name": "id", "in": "path", "description": "Organisation", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "uuid", "in": "path", "description": "Jambe", "required": true, "schema": {"type": "string"}}], "responses": {"204": {"description": "Appel coupé"}, "403": {"description": "`interdit` (permission `diagnostic.agir`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas d'appel en cours de ce nom chez ses clients", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "503": {"description": "`moteur_injoignable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/appels.csv": {"get": {"tags": ["journal"], "summary": "Export CSV des appels de tous les clients d'un opérateur ou d'un revendeur (et de ses\nrevendeurs), du plus ancien au plus récent : la base de la facturation (D13).", "operationId": "exporterAppelsDuParc", "parameters": [{"name": "id", "in": "path", "description": "Opérateur ou revendeur", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "du", "in": "query", "description": "Début de la période (RFC 3339), inclus.", "required": false, "schema": {"type": ["string", "null"], "format": "date-time"}}, {"name": "au", "in": "query", "description": "Fin de la période (RFC 3339), exclue.", "required": false, "schema": {"type": ["string", "null"], "format": "date-time"}}, {"name": "sens", "in": "query", "description": "`entrant`, `sortant` ou `interne`.", "required": false, "schema": {"type": ["string", "null"]}}, {"name": "poste", "in": "query", "description": "Appels d'un poste ; le titulaire du poste voit les siens.", "required": false, "schema": {"type": ["string", "null"]}}, {"name": "limite", "in": "query", "description": "Appels par page (100 par défaut, 500 au plus).", "required": false, "schema": {"type": ["integer", "null"], "format": "int64"}}, {"name": "avant", "in": "query", "description": "Page suivante : `suivant` de la page précédente.", "required": false, "schema": {"type": ["string", "null"], "format": "date-time"}}, {"name": "numeros", "in": "query", "description": "`complets` : numéros en entier (permission `journal.voir_numeros`, tracé).", "required": false, "schema": {"type": ["string", "null"]}}, {"name": "repondu", "in": "query", "description": "Vrai : appels répondus (un entrant mis en relation avec une personne, D66) ; faux : appels\nmanqués (ni mis en relation ni message) et sortants sans réponse.", "required": false, "schema": {"type": ["boolean", "null"]}}, {"name": "issue", "in": "query", "description": "Issue (D66) : `repondu`, `manque` ou `message` (entrant), `sans_reponse` (sortant ou\ninterne non décroché).", "required": false, "schema": {"type": ["string", "null"]}}, {"name": "duree_min", "in": "query", "description": "Durée minimale, en secondes décrochées.", "required": false, "schema": {"type": ["integer", "null"], "format": "int32"}}, {"name": "mois", "in": "query", "description": "Mois `AAAA-MM` à l'heure de Paris (export du parc) : remplace `du` et `au`, comme la\nconsommation.", "required": false, "schema": {"type": ["string", "null"]}}, {"name": "recherche", "in": "query", "description": "Recherche (100 caractères au plus) : un numéro, même partiel, saisi en national (`06…`),\nen `00…` ou en `+33…`, un poste, ou le nom d'un contact (poste, répertoire commun,\ncontacts personnels du compte ; sans accents ni casse). Indisponible sur des numéros\nmasqués.", "required": false, "schema": {"type": ["string", "null"]}}], "responses": {"200": {"description": "CSV dans la langue de l'appelant (français : `;` et virgule décimale ; anglais : `,` et point), heures au fuseau du client, montants HT selon le rôle", "content": {"text/csv": {"schema": {"type": "string"}}}}, "403": {"description": "`interdit` (permission `journal.lire`, ou `journal.voir_numeros` pour les numéros en entier)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`journal_invalide` : sens, issue ou durée minimale invalide, recherche (export d'un client seulement), plus de 200 000 appels ; `mois_invalide`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/assistance": {"get": {"tags": ["reglages"], "summary": "État de l'accès de l'assistance de l'éditeur.", "operationId": "lireAssistance", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "État", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/EtatAssistance"}}}}, "403": {"description": "`interdit` : pas l'équipe de l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["reglages"], "summary": "Ouvre l'accès de l'assistance pour une durée limitée (7 jours au plus). Tracé.", "operationId": "ouvrirAssistance", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/OuvertureAssistance"}}}, "required": true}, "responses": {"200": {"description": "État", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/EtatAssistance"}}}}, "403": {"description": "`interdit` : pas l'équipe de l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`duree_invalide` : de 1 à 168 heures", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "delete": {"tags": ["reglages"], "summary": "Ferme l'accès de l'assistance, aussitôt. Tracé.", "operationId": "fermerAssistance", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"204": {"description": "Fermé"}, "403": {"description": "`interdit` : pas l'équipe de l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/assistant": {"get": {"tags": ["assistant"], "summary": "Réglage de l'assistant, sans la clé.", "operationId": "lireReglageAssistant", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Assistant réglé", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReglageAssistant"}}}}, "403": {"description": "`interdit` (permission `reglages.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur, ou assistant non réglé", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["assistant"], "summary": "Règle l'assistant de configuration : clé Claude de l'opérateur, modèle, budgets, tarif.", "operationId": "reglerAssistant", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/NouveauReglageAssistant"}}}, "required": true}, "responses": {"200": {"description": "Assistant réglé", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReglageAssistant"}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`assistant_invalide` : clé absente au premier réglage, modèle, budget ou prix invalide", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "delete": {"tags": ["assistant"], "summary": "Retire l'assistant : plus personne ne peut l'utiliser ; la clé est effacée.", "operationId": "retirerAssistant", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"204": {"description": "Assistant retiré"}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/audit": {"get": {"tags": ["diagnostic"], "summary": "Journal d'audit d'une organisation et de sa descendance.", "operationId": "lireAudit", "parameters": [{"name": "id", "in": "path", "description": "Organisation", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "avant", "in": "query", "description": "Entrées dont le rang est inférieur (page suivante) ; absent : les plus récentes.", "required": false, "schema": {"type": ["integer", "null"], "format": "int64"}}, {"name": "limite", "in": "query", "description": "Entrées par page (50 par défaut, 200 au plus).", "required": false, "schema": {"type": ["integer", "null"], "format": "int64"}}, {"name": "action", "in": "query", "description": "Début de l'action ou action exacte (`utilisateur.`, `connexion`).", "required": false, "schema": {"type": ["string", "null"]}}, {"name": "resultat", "in": "query", "description": "`succes`, `refus` ou `echec`.", "required": false, "schema": {"type": ["string", "null"]}}, {"name": "bannissements_automatiques", "in": "query", "description": "`false` : sans les bannissements automatiques de la garde (`garde.bannir` par le\nsystème, D43), nombreux ; ceux faits par une personne restent. Absent : tout.", "required": false, "schema": {"type": ["boolean", "null"]}}], "responses": {"200": {"description": "Entrées, des plus récentes aux plus anciennes", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PageAudit"}}}}, "403": {"description": "`interdit` (permission `audit.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/cles-api": {"get": {"tags": ["cles-api"], "summary": "Clés d'API d'une organisation (sans leur secret).", "operationId": "listerClesApi", "parameters": [{"name": "id", "in": "path", "description": "Organisation", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Clés, révoquées comprises", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/Cle"}}}}}, "403": {"description": "`interdit`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "post": {"tags": ["cles-api"], "summary": "Crée une clé d'API pour une organisation.", "operationId": "creerCleApi", "parameters": [{"name": "id", "in": "path", "description": "Organisation de la clé", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/DemandeCle"}}}, "required": true}, "responses": {"201": {"description": "Clé créée ; `secret` n'est donné qu'une fois", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CleCreee"}}}}, "403": {"description": "`interdit` (permission `cle_api.gerer`, ou appel par une clé) ; `escalade_interdite` : la clé pourrait faire plus que son créateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`role_invalide`, `permission_inconnue`, `nom_invalide`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/clients": {"get": {"tags": ["clients"], "summary": "Clients visibles depuis une organisation (sa descendance).", "operationId": "listerClients", "parameters": [{"name": "id", "in": "path", "description": "Organisation de départ", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Clients", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/Client"}}}}}, "403": {"description": "`interdit` (permission `client.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "post": {"tags": ["clients"], "summary": "Crée un client sous un opérateur ou un revendeur, avec son domaine SIP.", "operationId": "creerClient", "parameters": [{"name": "id", "in": "path", "description": "Opérateur ou revendeur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/NouveauClient"}}}, "required": true}, "responses": {"201": {"description": "Client et domaine SIP créés", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Client"}}}}, "403": {"description": "`interdit` (permission `client.creer`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`domaine_existant`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`nom_invalide`, `domaine_invalide`, `parent_invalide`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/comptes": {"get": {"tags": ["organisations"], "summary": "Comptes d'une organisation (les siens, pas ceux de sa descendance).", "operationId": "listerComptes", "parameters": [{"name": "id", "in": "path", "description": "Organisation", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Comptes", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/CompteEquipe"}}}}}, "403": {"description": "`interdit` (permission `utilisateur.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "post": {"tags": ["organisations"], "summary": "Crée un compte d'équipe chez l'opérateur (admin ou support) ou chez un revendeur (admin), et\nlui envoie son invitation par e-mail. Le second facteur lui sera demandé à sa première\nconnexion (§6).", "operationId": "creerCompte", "parameters": [{"name": "id", "in": "path", "description": "Opérateur ou revendeur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/NouveauCompte"}}}, "required": true}, "responses": {"201": {"description": "Compte créé", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CompteEquipe"}}}}, "403": {"description": "`interdit` (permission `utilisateur.creer`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`courriel_pris`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`compte_de_client` (un client : passer par ses utilisateurs), `nom_invalide`, `courriel_invalide`, `role_invalide`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/consommation": {"get": {"tags": ["grilles"], "summary": "Consommation des clients d'une organisation (opérateur ou revendeur) sur un mois.", "operationId": "lireConsommation", "parameters": [{"name": "id", "in": "path", "description": "Opérateur ou revendeur", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "mois", "in": "query", "description": "Mois `AAAA-MM` ; absent : le mois en cours.", "required": false, "schema": {"type": ["string", "null"]}}, {"name": "client", "in": "query", "description": "Un seul client (fiche du client) ; absent : tous.", "required": false, "schema": {"type": ["string", "null"], "format": "uuid"}}], "responses": {"200": {"description": "Consommation par client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Consommation"}}}}, "403": {"description": "`interdit` (permission `grille.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : ni l'opérateur ni un revendeur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`mois_invalide`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/destinations-bloquees": {"get": {"tags": ["garde"], "summary": "Destinations bloquées pour tous les clients (D23).", "operationId": "listerDestinationsBloquees", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Préfixes bloqués", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/DestinationBloquee"}}}}}, "403": {"description": "`interdit` (permission `reglages.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["garde"], "summary": "Remplace les destinations bloquées ; les routes sortantes de tous les clients sont réécrites\ndans la même transaction. Les urgences restent toujours joignables (D22).", "operationId": "bloquerDestinations", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/DestinationBloquee"}}}}, "required": true}, "responses": {"200": {"description": "Préfixes bloqués", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/DestinationBloquee"}}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`prefixe_invalide`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/devise": {"get": {"tags": ["reglages"], "summary": "Devise de l'instance, lue depuis n'importe quelle organisation dont on lit les réglages.", "operationId": "lireDevise", "parameters": [{"name": "id", "in": "path", "description": "Organisation", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Devise de l'instance", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/DeviseInstance"}}}}, "403": {"description": "`interdit` (permission `reglages.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["reglages"], "summary": "Règle la devise de l'instance (opérateur seulement). Sans conversion : refusé dès qu'une\ngrille tarifaire existe ou qu'un appel a été valorisé, sauf pour garder la même devise.", "operationId": "reglerDevise", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReglageDevise"}}}, "required": true}, "responses": {"200": {"description": "Devise de l'instance", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/DeviseInstance"}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`devise_tarifs_existants` : une grille tarifaire existe ou un appel a été valorisé ; les montants ne sont pas convertis", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`devise_invalide` : pas une devise prise en charge", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/diagnostic/recharger": {"post": {"tags": ["diagnostic"], "summary": "Recharge la configuration du moteur de téléphonie : caches vidés, configuration, dialplan et\nACL relus. Pour l'opérateur (toute l'instance) ; tracé.", "operationId": "rechargerConfiguration", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"204": {"description": "Configuration rechargée"}, "403": {"description": "`interdit` (permission `diagnostic.agir` sur un opérateur)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "503": {"description": "`moteur_injoignable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/diagnostic/redemarrer": {"post": {"tags": ["diagnostic"], "summary": "Redémarre le moteur de téléphonie, après les appels en cours ou tout de suite.\nToute l'instance : réservé à l'admin de l'opérateur ; tracé.", "operationId": "redemarrerMoteur", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/Redemarrage"}}}, "required": true}, "responses": {"202": {"description": "Redémarrage demandé"}, "403": {"description": "`interdit` (permission `reglages.modifier` sur l'opérateur)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "503": {"description": "`moteur_injoignable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/fonctions": {"get": {"tags": ["organisations"], "summary": "Fonctions activées sur l'instance.", "operationId": "lireFonctions", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Fonctions", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Fonctions"}}}}, "403": {"description": "`interdit` (permission `reglages.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["organisations"], "summary": "Active ou coupe les revendeurs, l'assistant IA et la messagerie vocale. Couper la messagerie\ndésactive toutes les boîtes (leur état est gardé, leurs messages aussi) ; la réactiver rend à\nchaque boîte son état d'avant.", "operationId": "reglerFonctions", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/Fonctions"}}}, "required": true}, "responses": {"200": {"description": "Fonctions", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Fonctions"}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`revendeurs_existants` : des revendeurs existent encore", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/fuseau": {"get": {"tags": ["reglages"], "summary": "Fuseau d'une organisation.", "operationId": "lireFuseau", "parameters": [{"name": "id", "in": "path", "description": "Organisation", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Fuseau", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/FuseauOrganisation"}}}}, "403": {"description": "`interdit` (permission `reglages.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["reglages"], "summary": "Règle le fuseau d'une organisation (opérateur, revendeur ou client). Celui de l'opérateur ou\nd'un revendeur vaut pour les clients créés ensuite. Les horaires publiés d'un client passent\naussitôt à son nouveau fuseau.", "operationId": "reglerFuseau", "parameters": [{"name": "id", "in": "path", "description": "Organisation", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/FuseauOrganisation"}}}, "required": true}, "responses": {"200": {"description": "Fuseau", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/FuseauOrganisation"}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`fuseau_invalide` : pas un nom de `GET /fuseaux`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/garde": {"get": {"tags": ["garde"], "summary": "Réglages du bannissement et adresses bannies en ce moment.", "operationId": "lireGarde", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Réglages et bannissements en cours", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Garde"}}}}, "403": {"description": "`interdit` (permission `diagnostic.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["garde"], "summary": "Change seuil, fenêtre, durée et liste blanche.", "operationId": "reglerGarde", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReglagesGarde"}}}, "required": true}, "responses": {"200": {"description": "Réglages enregistrés", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReglagesGarde"}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`reglage_invalide`, `reseau_invalide`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/garde/bannies": {"post": {"tags": ["garde"], "summary": "Bannit une adresse à la main (§8), pour SIP et RTP : un scanner, un appareil à couper. Refusé\npour une adresse de la liste blanche ou d'un trunk. Tracé.", "operationId": "bannir", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/NouveauBannissement"}}}, "required": true}, "responses": {"204": {"description": "Adresse bannie"}, "403": {"description": "`interdit` (permission `diagnostic.agir`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`ip_epargnee` : liste blanche ou réseau d'un trunk", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`ip_invalide` ; `garde_invalide` : durée hors bornes", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/garde/bannies/{ip}": {"delete": {"tags": ["garde"], "summary": "Lève le bannissement d'une adresse.", "operationId": "debannir", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "ip", "in": "path", "description": "Adresse bannie", "required": true, "schema": {"type": "string"}}], "responses": {"204": {"description": "Bannissement levé"}, "403": {"description": "`interdit` (permission `diagnostic.agir`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur, ou adresse non bannie", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`ip_invalide`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/grille": {"get": {"tags": ["grilles"], "summary": "Grille attribuée à un client ou à un revendeur ; `null` : celle par défaut.", "operationId": "lireGrilleAttribuee", "parameters": [{"name": "id", "in": "path", "description": "Client ou revendeur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Grille attribuée", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AttributionGrille"}}}}, "403": {"description": "`interdit` (permission `grille.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["grilles"], "summary": "Attribue une grille de vente à un client (vente au client) ou à un revendeur (vente au\nrevendeur) ; sans grille : celle par défaut reprend. Il faut gérer les grilles de\nl'organisation et du propriétaire de la grille : un revendeur ne s'attribue pas une grille de\nl'opérateur.", "operationId": "attribuerGrille", "parameters": [{"name": "id", "in": "path", "description": "Client ou revendeur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/AttributionGrille"}}}, "required": true}, "responses": {"204": {"description": "Grille attribuée (ou retirée)"}, "403": {"description": "`interdit` (permission `grille.gerer` sur l'organisation et sur le propriétaire de la grille)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : grille", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`grille_invalide` : nature qui ne convient pas à cette organisation, ou grille hors de sa lignée", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/grilles": {"get": {"tags": ["grilles"], "summary": "Grilles de l'organisation (opérateur ou revendeur).", "operationId": "listerGrilles", "parameters": [{"name": "id", "in": "path", "description": "Opérateur ou revendeur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Grilles, par nature puis date d'effet", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/GrilleTarifaire"}}}}}, "403": {"description": "`interdit` (permission `grille.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "post": {"tags": ["grilles"], "summary": "Crée une grille, depuis un CSV (`prefixe;destination;prix_minute;frais;palier`) ou depuis\nune grille existante majorée d'une marge.", "operationId": "creerGrille", "parameters": [{"name": "id", "in": "path", "description": "Opérateur ou revendeur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/NouvelleGrilleTarifaire"}}}, "required": true}, "responses": {"201": {"description": "Grille créée", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/GrilleTarifaire"}}}}, "403": {"description": "`interdit` (permission `grille.gerer`, ou `grille.lire` sur la grille de départ)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : grille de départ", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`grille_invalide` : nature interdite à cette organisation, nom vide, ni CSV ni grille de départ (ou les deux), ligne du CSV fautive (numéro et raison, dont un second bouchon `*`), prix du bouchon invalide ou donné pour une grille d'achat ; `forfait_invalide` : forfait pour une grille d'achat, ou montant hors de 0 à 100 000 dans la devise de l'instance", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/langue": {"get": {"tags": ["reglages"], "summary": "Langue d'une organisation.", "operationId": "lireLangue", "parameters": [{"name": "id", "in": "path", "description": "Organisation", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Langue", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/LangueOrganisation"}}}}, "403": {"description": "`interdit` (permission `reglages.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["reglages"], "summary": "Règle la langue des e-mails d'une organisation (opérateur, revendeur ou client). Celle de\nl'opérateur ou d'un revendeur vaut pour ses comptes et pour les clients créés ensuite.", "operationId": "reglerLangue", "parameters": [{"name": "id", "in": "path", "description": "Organisation", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/LangueOrganisation"}}}, "required": true}, "responses": {"200": {"description": "Langue", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/LangueOrganisation"}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`langue_invalide` : ni français ni anglais", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/licence": {"get": {"tags": ["reglages"], "summary": "Licence de l'instance : identité, clé publique, utilisateurs et derniers relevés.", "operationId": "lireLicence", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Licence", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Licence"}}}}, "403": {"description": "`interdit` (permission `reglages.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/licence/fichier": {"put": {"tags": ["reglages"], "summary": "Charge la licence remise par l'éditeur (mode manuel, sans Hub). Elle doit être signée par\nl'éditeur et délivrée à cette instance ; une licence plus courte que celle en place est\nignorée.", "operationId": "chargerLicence", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/FichierLicence"}}}, "required": true}, "responses": {"200": {"description": "État de la licence", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/EtatLicence"}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`licence_invalide` : signature fausse, autre instance ou contenu illisible", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/licence/releves/{jour}": {"get": {"tags": ["reglages"], "summary": "Relevé signé d'un jour, à transmettre à l'éditeur (relevé manuel).", "operationId": "telechargerReleveLicence", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "jour", "in": "path", "description": "Jour (`AAAA-MM-JJ`)", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "Relevé signé (fichier JSON)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReleveSigne"}}}}, "403": {"description": "`interdit` (permission `reglages.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur, ou pas de relevé ce jour-là", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/machine": {"get": {"tags": ["diagnostic"], "summary": "Supervision de la machine : processeur, mémoire, charge et disques, minute par minute.", "operationId": "lireMachine", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "heures", "in": "query", "description": "Heures couvertes, jusqu'à maintenant (24 par défaut, 48 au plus).", "required": false, "schema": {"type": ["integer", "null"], "format": "int64"}}], "responses": {"200": {"description": "Relevés", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Machine"}}}}, "403": {"description": "`interdit` (permission `diagnostic.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`periode_invalide` : heures de 1 à 48", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/marque": {"put": {"tags": ["reglages"], "summary": "Règle le nom et les couleurs de la marque ; une valeur absente revient à celle par défaut.\nL'accent doit laisser lisible le texte blanc des boutons (contraste de 4,5 au moins), le menu\nun texte clair ou foncé (4,5), les textes le fond des pages (7).", "operationId": "reglerMarque", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReglageMarque"}}}, "required": true}, "responses": {"200": {"description": "Marque", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Marque"}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`nom_invalide`, `couleur_invalide` (pas `#rrggbb`), `couleur_peu_lisible` (texte blanc illisible dessus), `couleur_menu_peu_lisible` (aucun texte lisible sur ce menu), `couleur_texte_peu_lisible` (textes illisibles sur le fond des pages)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/marque/icone": {"put": {"tags": ["reglages"], "summary": "Dépose l'icône (favicon, application installée) : PNG carré de 192 pixels de côté au moins\net de 256 Kio au plus. Le logo n'est pas repris : souvent large, il serait illisible en\n16 pixels.", "operationId": "deposerIcone", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"description": "PNG carré", "content": {"application/octet-stream": {"schema": {"type": "array", "items": {"type": "integer", "format": "int32", "minimum": 0}}}}, "required": true}, "responses": {"200": {"description": "Marque", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Marque"}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "413": {"description": "`icone_trop_grosse` : plus de 256 Kio", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`icone_invalide` : pas un PNG carré de 192 pixels de côté au moins", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "delete": {"tags": ["reglages"], "summary": "Retire l'icône déposée : l'icône générée (initiale sur l'accent) revient.", "operationId": "retirerIcone", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Marque", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Marque"}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/marque/logo": {"put": {"tags": ["reglages"], "summary": "Dépose le logo : PNG, JPEG ou WebP de 256 Kio au plus. Le portail l'affiche à 28 pixels de\nhaut (56 en haute densité) : un logo carré ou large et sobre rend le mieux.", "operationId": "deposerLogo", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"description": "Image", "content": {"application/octet-stream": {"schema": {"type": "array", "items": {"type": "integer", "format": "int32", "minimum": 0}}}}, "required": true}, "responses": {"200": {"description": "Marque", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Marque"}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "413": {"description": "`logo_trop_gros` : plus de 256 Kio", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`logo_invalide` : ni PNG, ni JPEG, ni WebP", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "delete": {"tags": ["reglages"], "summary": "Retire le logo.", "operationId": "retirerLogo", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"204": {"description": "Logo retiré"}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/numeros": {"get": {"tags": ["numeros"], "summary": "Numéros visibles depuis une organisation : tous pour l'opérateur ; pour un revendeur, ses\nréservés et ceux de ses clients ; pour un client, les siens.", "operationId": "listerNumeros", "parameters": [{"name": "id", "in": "path", "description": "Organisation", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "etat", "in": "query", "description": "Seulement les numéros dans cet état.", "required": false, "schema": {"type": ["string", "null"]}}], "responses": {"200": {"description": "Numéros", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/Numero"}}}}}, "403": {"description": "`interdit` (permission `numero.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`etat_invalide`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "post": {"tags": ["numeros"], "summary": "Ajoute des numéros au stock de l'opérateur, libres. Tout ou rien.", "operationId": "creerNumeros", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/NouveauxNumeros"}}}, "required": true}, "responses": {"201": {"description": "Numéros ajoutés au stock", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/Numero"}}}}}, "403": {"description": "`interdit` (permission `numero.gerer`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`numero_existant`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`numero_invalide`, `pays_invalide` (pays à préciser, ou qui ne correspond pas à l'indicatif), `organisation_invalide` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/pays": {"get": {"tags": ["reglages"], "summary": "Pays d'une organisation.", "operationId": "lirePays", "parameters": [{"name": "id", "in": "path", "description": "Organisation", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Pays", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PaysOrganisation"}}}}, "403": {"description": "`interdit` (permission `reglages.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["reglages"], "summary": "Règle le pays d'une organisation (opérateur, revendeur ou client). Celui de l'opérateur ou\nd'un revendeur vaut pour les clients créés ensuite. Pour un client, ses routes sortantes et\nson parcours publié passent aussitôt au plan de numérotation du nouveau pays ; refusé si un\nposte ou un module porte l'un de ses numéros d'urgence, si une grille horaire publiée ferme un\njour férié absent du nouveau pays, ou si des renvois ou des numéros externes du parcours,\ncomposés dans l'ancien pays, changeraient de sens.", "operationId": "reglerPays", "parameters": [{"name": "id", "in": "path", "description": "Organisation", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/PaysOrganisation"}}}, "required": true}, "responses": {"200": {"description": "Pays", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PaysOrganisation"}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`pays_urgence_occupee` : un poste ou un module porte un numéro d'urgence du pays ; `pays_feries` : grilles horaires qui ferment un jour férié absent du pays, à décocher d'abord ; `pays_destinations_externes` : renvois ou numéros externes à retirer d'abord", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`pays_invalide` : pas un pays de `GET /pays`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/plafond": {"get": {"tags": ["reglages"], "summary": "Seuils par défaut de l'instance.", "operationId": "lirePlafondParDefaut", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Seuils par défaut", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SeuilsPlafond"}}}}, "403": {"description": "`interdit` (permission `reglages.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["reglages"], "summary": "Règle les seuils par défaut de l'instance.", "operationId": "reglerPlafondParDefaut", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/SeuilsPlafond"}}}, "required": true}, "responses": {"200": {"description": "Seuils par défaut", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SeuilsPlafond"}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`plafond_invalide`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/profils-trunk": {"get": {"tags": ["trunks"], "summary": "Profils de trunk de l'opérateur.", "operationId": "listerProfilsTrunk", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Profils, par nom", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/ProfilTrunk"}}}}}, "403": {"description": "`interdit` (permission `trunk.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "post": {"tags": ["trunks"], "summary": "Crée un profil de trunk.", "operationId": "creerProfilTrunk", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/NouveauProfilTrunk"}}}, "required": true}, "responses": {"201": {"description": "Profil créé", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProfilTrunk"}}}}, "403": {"description": "`interdit` (permission `trunk.gerer`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`profil_existant` : nom déjà pris", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`nom_invalide`, `proxy_invalide`, `format_invalide`, `reseau_invalide`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/profils-trunk/{profil_id}": {"put": {"tags": ["trunks"], "summary": "Modifie un profil de trunk : les trunks qui en sont tirés suivent (passerelles, routes\nsortantes, ACL des fournisseurs).", "operationId": "modifierProfilTrunk", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "profil_id", "in": "path", "description": "Profil", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/NouveauProfilTrunk"}}}, "required": true}, "responses": {"200": {"description": "Profil modifié", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProfilTrunk"}}}}, "403": {"description": "`interdit` (permission `trunk.gerer`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur, ou pas de profil", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`profil_existant` : nom déjà pris", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`nom_invalide`, `proxy_invalide`, `format_invalide`, `reseau_invalide`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "delete": {"tags": ["trunks"], "summary": "Supprime un profil de trunk qu'aucun trunk n'utilise.", "operationId": "supprimerProfilTrunk", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "profil_id", "in": "path", "description": "Profil", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"204": {"description": "Profil supprimé"}, "403": {"description": "`interdit` (permission `trunk.gerer`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur, ou pas de profil", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`profil_utilise` : des trunks en sont tirés", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/retention": {"get": {"tags": ["reglages"], "summary": "Rétentions d'une organisation : réglées et appliquées.", "operationId": "lireRetention", "parameters": [{"name": "id", "in": "path", "description": "Opérateur ou client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Rétentions", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Retention"}}}}, "403": {"description": "`interdit` (permission `reglages.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : ni l'opérateur ni un client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["reglages"], "summary": "Règle les rétentions d'une organisation. Bornes : enregistrements de 1 à 183 jours (D63),\nmessages de 1 à 3 650 jours, CDR de 365 à 3 650 jours (CPCE L34-1) ; `null` : le niveau\nau-dessus.", "operationId": "reglerRetention", "parameters": [{"name": "id", "in": "path", "description": "Opérateur ou client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/Durees"}}}, "required": true}, "responses": {"200": {"description": "Rétentions", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Retention"}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : ni l'opérateur ni un client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`retention_invalide` : durée hors des bornes", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/revendeurs": {"get": {"tags": ["organisations"], "summary": "Revendeurs visibles depuis une organisation (sa descendance), avec leur nombre de clients.", "operationId": "listerRevendeurs", "parameters": [{"name": "id", "in": "path", "description": "Organisation de départ", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Revendeurs", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/Revendeur"}}}}}, "403": {"description": "`interdit` (permission `organisation.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "post": {"tags": ["organisations"], "summary": "Crée un revendeur sous l'opérateur. Ses clients se créent ensuite sous lui\n(`POST /organisations/{id}/clients`), ses admins par `POST /organisations/{id}/comptes`.", "operationId": "creerRevendeur", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/NouveauRevendeur"}}}, "required": true}, "responses": {"201": {"description": "Revendeur créé", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Revendeur"}}}}, "403": {"description": "`interdit` (permission `revendeur.creer`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`revendeurs_desactives` : revendeurs coupés par l'opérateur (D94)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`nom_invalide`, `parent_invalide` : un revendeur dépend de l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/sante": {"get": {"tags": ["diagnostic"], "summary": "Santé de l'instance : moteur de téléphonie, base, CDR, trunks et webhooks des clients de\nl'organisation.", "operationId": "santeInstance", "parameters": [{"name": "id", "in": "path", "description": "Organisation", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Santé", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Sante"}}}}, "403": {"description": "`interdit` (permission `diagnostic.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/simultanes": {"get": {"tags": ["journal"], "summary": "Pics d'appels simultanés heure par heure (opérateur, revendeur ou client) : le plus grand\nnombre d'appels en cours au même instant, d'après le début et la fin des CDR.", "operationId": "lireSimultanes", "parameters": [{"name": "id", "in": "path", "description": "Opérateur, revendeur ou client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "periode", "in": "query", "description": "Période (`jour`, `24h`, `7j`, `30j`, `mois`) ; les 24 dernières heures par défaut.", "required": false, "schema": {"oneOf": [{"$ref": "#/components/schemas/PeriodeModule"}, {"type": "null"}]}}], "responses": {"200": {"description": "Pics par heure", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Simultanes"}}}}, "403": {"description": "`interdit` (permission `journal.lire` ; un collaborateur n'a pas les chiffres du client)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`periode_invalide` : période en direct ou sur l'année", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/smtp": {"get": {"tags": ["reglages"], "summary": "Le serveur SMTP de l'opérateur, sans son mot de passe.", "operationId": "lireSmtp", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Serveur SMTP réglé", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReglageSmtp"}}}}, "403": {"description": "`interdit` (permission `reglages.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur, ou aucun serveur réglé", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["reglages"], "summary": "Règle le serveur SMTP de l'opérateur (remplace le précédent).", "operationId": "reglerSmtp", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/NouveauReglageSmtp"}}}, "required": true}, "responses": {"200": {"description": "Serveur SMTP réglé", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReglageSmtp"}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`smtp_invalide` : hôte, port, sécurité ou adresse d'expédition invalide, mot de passe manquant", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "delete": {"tags": ["reglages"], "summary": "Retire le serveur SMTP : plus aucun e-mail ne part.", "operationId": "retirerSmtp", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"204": {"description": "Serveur SMTP retiré"}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/smtp/essai": {"post": {"tags": ["reglages"], "summary": "Envoie un e-mail d'essai par le serveur réglé. L'erreur du serveur est rendue telle quelle\npour le diagnostic (authentification refusée, TLS, hôte injoignable).", "operationId": "essayerSmtp", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/EssaiSmtp"}}}, "required": true}, "responses": {"204": {"description": "E-mail accepté par le serveur"}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur, ou aucun serveur réglé", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`smtp_invalide` : adresse du destinataire invalide", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "502": {"description": "`smtp_echec` : le serveur a refusé ou n'a pas répondu (détail du serveur)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/sso/jeton": {"get": {"tags": ["reglages"], "summary": "Connexion par jeton du portail de l'opérateur : état de la clé.", "operationId": "lireSsoJeton", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Réglage", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReglageSsoJeton"}}}}, "403": {"description": "`interdit` (permission `reglages.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "post": {"tags": ["reglages"], "summary": "Crée (ou remplace) la clé de connexion par jeton ; elle est rendue une fois. L'ancienne ne\nvaut plus rien.", "operationId": "creerSsoJeton", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Nouvelle clé (affichée cette fois seulement)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CleSsoJeton"}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "delete": {"tags": ["reglages"], "summary": "Ferme la connexion par jeton : la clé est effacée.", "operationId": "retirerSsoJeton", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"204": {"description": "Clé effacée"}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/sso/oidc": {"get": {"tags": ["reglages"], "summary": "Annuaire réglé sur une organisation.", "operationId": "lireSsoOidc", "parameters": [{"name": "id", "in": "path", "description": "Opérateur ou client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Réglage (sans le secret)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReglageOidc"}}}}, "403": {"description": "`interdit` (permission `reglages.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : aucun annuaire réglé, ou ni l'opérateur ni un client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["reglages"], "summary": "Règle l'annuaire d'une organisation. L'émetteur est vérifié (document de découverte lu) avant\nl'enregistrement.", "operationId": "reglerSsoOidc", "parameters": [{"name": "id", "in": "path", "description": "Opérateur ou client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/NouveauReglageOidc"}}}, "required": true}, "responses": {"200": {"description": "Réglage enregistré", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReglageOidc"}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : ni l'opérateur ni un client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`oidc_invalide` : émetteur, identifiant, secret, libellé ou domaine invalide", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "502": {"description": "`oidc_injoignable` : document de découverte illisible", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "delete": {"tags": ["reglages"], "summary": "Retire l'annuaire d'une organisation et son secret.", "operationId": "retirerSsoOidc", "parameters": [{"name": "id", "in": "path", "description": "Opérateur ou client", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"204": {"description": "Annuaire retiré"}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : ni l'opérateur ni un client", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/statistiques": {"get": {"tags": ["journal"], "summary": "Statistiques des appels du parc : volume jour par jour, qualité des sortants par fournisseur.", "operationId": "statistiquesParc", "parameters": [{"name": "id", "in": "path", "description": "Opérateur ou revendeur", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "jours", "in": "query", "description": "Jours couverts, jusqu'à aujourd'hui compris (30 par défaut, 90 au plus).", "required": false, "schema": {"type": ["integer", "null"], "format": "int64"}}], "responses": {"200": {"description": "Statistiques de la période", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/StatistiquesParc"}}}}, "403": {"description": "`interdit` (permission `journal.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : ni l'opérateur ni un revendeur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`periode_invalide`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/suffixe-domaine": {"get": {"tags": ["clients"], "summary": "Suffixe des domaines clients (D108), pour qui crée des clients (l'opérateur et ses\nrevendeurs) ou consulte les réglages.", "operationId": "lireSuffixeDomaine", "parameters": [{"name": "id", "in": "path", "description": "Opérateur ou revendeur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Suffixe des domaines clients", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SuffixeDomaine"}}}}, "403": {"description": "`interdit` (permission `client.creer` ou `reglages.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["reglages"], "summary": "Règle le suffixe des domaines clients de l'instance (D108). Les clients existants gardent\nleur domaine.", "operationId": "reglerSuffixeDomaine", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/SuffixeDomaine"}}}, "required": true}, "responses": {"200": {"description": "Suffixe des domaines clients", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SuffixeDomaine"}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`suffixe_invalide`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/supervision": {"get": {"tags": ["organisations"], "summary": "État du jeton de supervision (jamais le jeton).", "operationId": "lireSupervision", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Jeton de supervision", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/JetonSupervision"}}}}, "403": {"description": "`interdit` (permission `reglages.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/supervision/jeton": {"post": {"tags": ["organisations"], "summary": "Crée le jeton de supervision, ou le remplace : l'ancien cesse aussitôt de servir.", "operationId": "creerJetonSupervision", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"201": {"description": "Jeton créé ; `secret` n'est donné qu'une fois", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/JetonSupervisionCree"}}}}, "403": {"description": "`interdit` (réservé à l'admin opérateur en personne : ni une clé d'API, ni l'assistance de l'éditeur)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "delete": {"tags": ["organisations"], "summary": "Révoque le jeton de supervision : `/metrics` redevient local seulement.", "operationId": "revoquerJetonSupervision", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"204": {"description": "Jeton révoqué (ou aucun)"}, "403": {"description": "`interdit` (réservé à l'admin opérateur en personne : ni une clé d'API, ni l'assistance de l'éditeur)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/synthese": {"get": {"tags": ["reglages"], "summary": "La voix de synthèse des annonces réglée par l'opérateur, sans la clé.", "operationId": "lireSynthese", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Réglage (Piper et voix Google par défaut si rien n'est réglé)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReglageSynthese"}}}}, "403": {"description": "`interdit` (permission `reglages.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["reglages"], "summary": "Règle la voix de synthèse des annonces : moteur, clé Google (gardée, remplacée ou effacée),\nvoix française et anglaise.", "operationId": "reglerSynthese", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/NouveauReglageSynthese"}}}, "required": true}, "responses": {"200": {"description": "Réglage enregistré", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReglageSynthese"}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`synthese_invalide` : voix (forme `fr-FR-Chirp3-HD-Leda`) ou clé invalide", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/synthese/essai": {"post": {"tags": ["reglages"], "summary": "Fait lire une courte phrase avec le réglage enregistré et renvoie le WAV. Sans secours :\nl'erreur de Google est rendue avec son détail pour le diagnostic (clé refusée, restriction\nd'IP, API non activée).", "operationId": "essayerSynthese", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/EssaiSynthese"}}}, "required": true}, "responses": {"200": {"description": "WAV mono 16 bits 8 kHz", "content": {"audio/wav": {"schema": {"type": "array", "items": {"type": "integer", "format": "int32", "minimum": 0}}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`synthese_invalide` : langue autre que fr ou en ; `synthese_google_sans_cle` : Google choisi sans clé enregistrée", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "500": {"description": "`synthese_echouee`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "502": {"description": "Refus de Google, détail de Google : `synthese_google_cle_invalide`, `synthese_google_restriction_ip` (clé restreinte à une autre adresse IP), `synthese_google_api_refusee` (API Text-to-Speech non activée, ou clé restreinte à d'autres API), `synthese_google_quota`, `synthese_google_voix_inconnue`, `synthese_google_refus`, `synthese_google_injoignable`, `synthese_google_reponse_invalide`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "503": {"description": "Piper choisi : `synthese_indisponible`, `synthese_anglaise_indisponible`, `synthese_occupee`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/tableau": {"get": {"tags": ["journal"], "summary": "Tableau de bord d'une organisation (opérateur, revendeur ou client) sur une période :\nappels et montants par tranche, comparaison, destinations, clients qui consomment le plus.", "operationId": "lireTableau", "parameters": [{"name": "id", "in": "path", "description": "Opérateur, revendeur ou client", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "periode", "in": "query", "description": "Période (`jour`, `24h`, `7j`, `30j`, `mois`, `annee`) ; le mois en cours par défaut.", "required": false, "schema": {"oneOf": [{"$ref": "#/components/schemas/PeriodeModule"}, {"type": "null"}]}}, {"name": "pas", "in": "query", "description": "Découpage ; par défaut l'heure sur un jour, le jour jusqu'au mois, le mois sur l'année.", "required": false, "schema": {"oneOf": [{"$ref": "#/components/schemas/Pas"}, {"type": "null"}]}}, {"name": "comparer", "in": "query", "description": "Ajoute les totaux de la période précédente de même longueur.", "required": false, "schema": {"type": "boolean"}}], "responses": {"200": {"description": "Tableau de la période", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Tableau"}}}}, "403": {"description": "`interdit` (permission `journal.lire` ; un collaborateur n'a pas les chiffres du client)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`periode_invalide` : période en direct, ou trop de tranches (800 au plus)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/transcription": {"get": {"tags": ["reglages"], "summary": "Le service de transcription de l'opérateur, sans sa clé.", "operationId": "lireTranscription", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Service réglé", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReglageTranscription"}}}}, "403": {"description": "`interdit` (permission `reglages.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur, ou aucun service réglé", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["reglages"], "summary": "Règle le service de transcription de l'opérateur (remplace le précédent).", "operationId": "reglerTranscription", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/NouveauReglageTranscription"}}}, "required": true}, "responses": {"200": {"description": "Service réglé", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ReglageTranscription"}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`transcription_invalide` : adresse (http ou https, sans requête), modèle ou langue invalide", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "delete": {"tags": ["reglages"], "summary": "Retire le service de transcription : plus rien n'est transcrit.", "operationId": "retirerTranscription", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"204": {"description": "Service retiré"}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/transcription/essai": {"post": {"tags": ["reglages"], "summary": "Fait transcrire une seconde de silence par le service réglé. L'erreur du service est rendue\ntelle quelle pour le diagnostic (clé refusée, modèle inconnu, hôte injoignable).", "operationId": "essayerTranscription", "parameters": [{"name": "id", "in": "path", "description": "Opérateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Le service a répondu", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/EssaiTranscription"}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : pas l'opérateur, ou aucun service réglé", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "502": {"description": "`transcription_echec` : le service a refusé ou n'a pas répondu (détail du service)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/webhook": {"get": {"tags": ["webhooks"], "summary": "L'endpoint de l'organisation.", "operationId": "lireWebhook", "parameters": [{"name": "id", "in": "path", "description": "Organisation", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Endpoint, sans son secret", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Webhook"}}}}, "403": {"description": "`interdit` (permission `reglages.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : aucun webhook", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "put": {"tags": ["webhooks"], "summary": "Crée ou modifie l'endpoint (et le réactive). À la création, le secret est rendu une fois.", "operationId": "reglerWebhook", "parameters": [{"name": "id", "in": "path", "description": "Organisation", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/NouveauWebhook"}}}, "required": true}, "responses": {"200": {"description": "Endpoint modifié, secret gardé", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Webhook"}}}}, "201": {"description": "Endpoint créé, avec son secret (affiché cette fois seulement)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/WebhookAvecSecret"}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`webhook_invalide` : adresse refusée (https, port 443 ou 8443, adresse publique qui résout), événement inconnu pour cette organisation", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "delete": {"tags": ["webhooks"], "summary": "Supprime l'endpoint, son secret et sa file.", "operationId": "supprimerWebhook", "parameters": [{"name": "id", "in": "path", "description": "Organisation", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"204": {"description": "Webhook supprimé"}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : aucun webhook", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/webhook/envois": {"get": {"tags": ["webhooks"], "summary": "Les 100 derniers envois de l'endpoint.", "operationId": "listerEnvoisWebhook", "parameters": [{"name": "id", "in": "path", "description": "Organisation", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Envois, du plus récent au plus ancien", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/Envoi"}}}}}, "403": {"description": "`interdit` (permission `reglages.lire`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/organisations/{id}/webhook/secret": {"post": {"tags": ["webhooks"], "summary": "Renouvelle le secret ; le nouveau est rendu une fois.", "operationId": "renouvelerSecretWebhook", "parameters": [{"name": "id", "in": "path", "description": "Organisation", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Nouveau secret (affiché cette fois seulement)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/WebhookAvecSecret"}}}}, "403": {"description": "`interdit` (permission `reglages.modifier`)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "404": {"description": "`introuvable` : aucun webhook", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/pays": {"get": {"tags": ["reglages"], "summary": "Pays pris en charge, avec leur plan de numérotation.", "operationId": "listerPays", "responses": {"200": {"description": "Pays pris en charge", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/PaysPrisEnCharge"}}}}}}, "security": [{"session": []}]}}, "/api/v1/provision/acrobits": {"get": {"tags": ["provisionnement"], "summary": "Configuration d'Acrobits (Account XML), relue chaque jour par l'application. Ouvert dans un\nnavigateur (QR code scanné à l'appareil photo), redirige vers l'application (`provlinks:`).", "operationId": "provisionnerAcrobits", "parameters": [{"name": "jeton", "in": "query", "description": "Jeton de provisionnement.", "required": true, "schema": {"type": "string"}}, {"name": "app", "in": "query", "description": "`1` : requête de l'application (sinon, redirection vers elle).", "required": false, "schema": {"type": ["string", "null"]}}], "responses": {"200": {"description": "Account XML", "content": {"application/xml": {"schema": {"type": "string"}}}}, "302": {"description": "Vers l'application (`provlinks://…&app=1`)"}, "404": {"description": "Lien invalide ou expiré, poste supprimé ou désactivé", "content": {"application/xml": {"schema": {"type": "string"}}}}}}}, "/api/v1/provision/acrobits-contacts": {"get": {"tags": ["provisionnement"], "summary": "Contacts du téléphone (format JSON d'Acrobits) : les autres postes du client et son\nrépertoire commun.", "operationId": "contactsAcrobits", "parameters": [{"name": "jeton", "in": "query", "description": "Jeton de provisionnement.", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "Contacts", "content": {"application/json": {"schema": {"type": "string"}}}}, "404": {"description": "`introuvable` : lien invalide ou expiré", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}}}, "/api/v1/provision/cloudsoftphone": {"get": {"tags": ["provisionnement"], "summary": "Provisionnement initial de l'application mobile de l'opérateur (Cloud Softphone), à régler\nchez Acrobits : `…/api/v1/provision/cloudsoftphone?p=%password%`. Refus : le message que\nl'application affiche.", "operationId": "provisionnerCloudSoftphone", "parameters": [{"name": "p", "in": "query", "description": "Jeton du lien CSC (`%password%` de l'URL réglée chez Acrobits).", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "Account XML", "content": {"application/xml": {"schema": {"type": "string"}}}}, "401": {"description": "Lien invalide ou expiré (`<error><message>`)", "content": {"application/xml": {"schema": {"type": "string"}}}}}}}, "/api/v1/provision/installation": {"post": {"tags": ["provisionnement"], "summary": "Page d'installation (lien envoyé par e-mail, sans session) : les liens d'installation du\nposte, renouvelés. POST : le jeton reste hors des journaux d'accès.", "operationId": "lireInstallation", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/JetonInstallation"}}}, "required": true}, "responses": {"200": {"description": "Liens d'installation", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Installation"}}}}, "404": {"description": "`introuvable` : lien invalide ou expiré, poste supprimé ou désactivé", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}}}, "/api/v1/provision/materiel/{dossier}/{fichier}": {"get": {"tags": ["provisionnement"], "summary": "Fichier d'un téléphone de bureau rangé sous sa MAC (`{mac}/annuaire.xml`).", "operationId": "servirFichierMaterielDossier", "parameters": [{"name": "dossier", "in": "path", "description": "Dossier (la MAC de l'appareil)", "required": true, "schema": {"type": "string"}}, {"name": "fichier", "in": "path", "description": "Nom du fichier demandé", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "Fichier", "content": {"application/xml": {"schema": {"type": "string"}}}}, "401": {"description": "Identifiants absents ou refusés (défi `WWW-Authenticate: Basic`)"}, "404": {"description": "Fichier que le profil de l'appareil ne sert pas"}}}}, "/api/v1/provision/materiel/{fichier}": {"get": {"tags": ["provisionnement"], "summary": "Fichier de configuration d'un téléphone de bureau (`{mac}.cfg`, `y000000000000.cfg`,\n`cfg{mac}.xml`…), composé à la demande d'après son profil. Authentification HTTP Basic :\nla MAC de l'appareil et son mot de passe (`revelerIdentifiantsAppareil`).", "operationId": "servirFichierMateriel", "parameters": [{"name": "fichier", "in": "path", "description": "Nom du fichier demandé", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "Fichier", "content": {"text/plain": {"schema": {"type": "string"}}}}, "401": {"description": "Identifiants absents ou refusés (défi `WWW-Authenticate: Basic`)"}, "404": {"description": "Fichier que le profil de l'appareil ne sert pas"}}}}, "/api/v1/sante": {"get": {"tags": ["exploitation"], "summary": "L'instance répond et sa base est joignable.", "operationId": "sante", "responses": {"200": {"description": "Instance opérationnelle", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Sante"}}}}, "503": {"description": "Base injoignable", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}}}, "/api/v1/second-facteur/passkeys": {"get": {"tags": ["connexion"], "summary": "Passkeys du compte connecté.", "operationId": "listerPasskeys", "responses": {"200": {"description": "Passkeys", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/ResumePasskey"}}}}}}, "security": [{"session": []}]}}, "/api/v1/second-facteur/passkeys/debut": {"post": {"tags": ["connexion"], "summary": "Commence l'enregistrement d'une passkey : options à passer à `navigator.credentials.create()`.", "operationId": "commencerPasskey", "responses": {"200": {"description": "Options WebAuthn de création (`publicKey`)", "content": {"application/json": {"schema": {}}}}, "409": {"description": "`etape_de_connexion_invalide`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/second-facteur/passkeys/fin": {"post": {"tags": ["connexion"], "summary": "Termine l'enregistrement. Si la session était limitée à l'inscription du second facteur, elle\ndevient complète (nouveau cookie).", "operationId": "terminerPasskey", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/FinInscription"}}}, "required": true}, "responses": {"200": {"description": "Passkey enregistrée", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PasskeyAjoutee"}}}}, "400": {"description": "`pas_de_ceremonie`, `passkey_refusee`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`nom_invalide`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/second-facteur/passkeys/{id}": {"delete": {"tags": ["connexion"], "summary": "Supprime une passkey du compte connecté.", "operationId": "supprimerPasskey", "parameters": [{"name": "id", "in": "path", "description": "Passkey", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"204": {"description": "Supprimée"}, "404": {"description": "`introuvable`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/second-facteur/totp": {"post": {"tags": ["connexion"], "summary": "Commence l'inscription d'une application d'authentification (TOTP).", "operationId": "commencerTotp", "responses": {"200": {"description": "Secret à configurer, valable jusqu'à confirmation", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/InscriptionTotp"}}}}, "409": {"description": "`second_facteur_deja_actif` ou `etape_de_connexion_invalide`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/second-facteur/totp/confirmation": {"post": {"tags": ["connexion"], "summary": "Confirme l'inscription par un premier code. Renvoie les codes de secours ; si la session\nétait limitée à l'inscription, elle devient complète (nouveau cookie).", "operationId": "confirmerTotp", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/Code"}}}, "required": true}, "responses": {"200": {"description": "Second facteur actif", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CodesDeSecours"}}}}, "400": {"description": "`code_invalide` ou `pas_d_inscription`", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/sso/jeton": {"get": {"tags": ["connexion"], "summary": "Connexion par jeton signé du portail de l'opérateur (D79) : l'outil y envoie le navigateur\nde son client. Jeton valable dix minutes au plus, une seule fois. Réussie : session ouverte\n(cookie) et retour au portail ; refusée : page de connexion avec `?sso=<code>` (`ferme`,\n`invalide`, `expire`, `deja_utilise`, `compte_inconnu`, `compte_inactif`).", "operationId": "connexionSsoJeton", "parameters": [{"name": "jeton", "in": "query", "description": "Jeton JWT signé HS256 par l'outil de l'opérateur.", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "Page qui ouvre le portail, avec le cookie de session ; ou la page de connexion et le motif du refus"}, "429": {"description": "`trop_de_requetes` : trop de tentatives depuis cette adresse", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}}}, "/api/v1/sso/oidc/debut": {"post": {"tags": ["connexion"], "summary": "Commence la connexion par l'annuaire de l'organisation du compte : renvoie l'adresse où\nenvoyer le navigateur. 404 `sso_absent` si aucun annuaire ne vaut pour cette adresse.", "operationId": "debutSsoOidc", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/DebutOidc"}}}, "required": true}, "responses": {"200": {"description": "Adresse de l'annuaire", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/RedirectionOidc"}}}}, "404": {"description": "`sso_absent` : aucun annuaire pour cette adresse", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "429": {"description": "`trop_de_requetes` : trop de tentatives depuis cette adresse", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "502": {"description": "`oidc_injoignable` : annuaire injoignable", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}}}, "/api/v1/sso/oidc/retour": {"get": {"tags": ["connexion"], "summary": "Retour de l'annuaire : le code est échangé contre l'`id_token`, vérifié, puis la session est\nouverte et le portail affiché ; sinon la page de connexion avec `?sso=<code>` (`invalide`,\n`expire`, `compte_inconnu`, `compte_inactif`, `annule`).", "operationId": "retourSsoOidc", "parameters": [{"name": "code", "in": "query", "required": false, "schema": {"type": ["string", "null"]}}, {"name": "state", "in": "query", "required": false, "schema": {"type": ["string", "null"]}}, {"name": "error", "in": "query", "description": "Refus de l'annuaire (la personne a annulé, par exemple).", "required": false, "schema": {"type": ["string", "null"]}}], "responses": {"200": {"description": "Page qui ouvre le portail, avec le cookie de session ; ou la page de connexion et le motif du refus"}, "429": {"description": "`trop_de_requetes` : trop de tentatives depuis cette adresse", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}}}, "/api/v1/utilisateurs/{id}": {"delete": {"tags": ["clients"], "summary": "Supprime un compte et son poste : extension, boîte vocale et messages, restrictions d'appel.\nRefusé tant que le parcours publié du client mène au poste : modifier le parcours d'abord.\nLe téléphone resté configuré ne fait pas bannir le site pendant 30 jours ; le désinstaller.\nJamais son propre compte.", "operationId": "supprimerCompte", "parameters": [{"name": "id", "in": "path", "description": "Utilisateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"204": {"description": "Compte (et poste) supprimés"}, "403": {"description": "`interdit` : permissions `utilisateur.modifier` et `poste.creer`, compte hors de portée, ou son propre compte", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`poste_utilise` : le parcours publié mène au poste (modules dans le détail)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}, "patch": {"tags": ["clients"], "summary": "Modifie un compte : nom (repris comme nom affiché de son poste), adresse e-mail, rôle du même\nniveau, désactivation ou réactivation, limitation au téléphone (D107). Désactivé, le compte\nperd ses sessions, ne compte plus pour la licence (D71), et son poste est mis hors service (il\nne s'enregistre plus, ne reçoit ni ne passe d'appel ; sa boîte vocale et ses réglages\nrestent). Jamais son propre rôle ni son propre état. L'adresse e-mail est l'identifiant de\nconnexion : jamais celle d'un compte de rôle supérieur ; changée, elle ferme les sessions et\nles applications autorisées du compte, annule ses liens d'invitation ou de mot de passe\noublié en attente, et prévient l'ancienne et la nouvelle adresse (une nouvelle invitation part\nà la nouvelle si le compte n'a pas encore choisi son mot de passe) ; l'avant et l'après vont\nau journal d'audit.", "operationId": "modifierCompte", "parameters": [{"name": "id", "in": "path", "description": "Utilisateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/ModificationCompte"}}}, "required": true}, "responses": {"204": {"description": "Compte modifié"}, "403": {"description": "`interdit` : permission `utilisateur.modifier`, compte hors de portée, son propre rôle ou état, ou l'adresse d'un compte de rôle supérieur ; `licence_bloquee` : réactivation refusée, licence échue depuis plus de 30 jours (D78) ; `ajout_utilisateurs_non_autorise` : réactivation par un compte du client alors que l'opérateur ne lui laisse pas l'ajout (D121)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`courriel_pris` : adresse déjà celle d'un autre compte", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`nom_invalide`, `courriel_invalide`, `role_invalide`, `texte_interdit`, `telephone_seulement_invalide` (un admin ne peut pas être limité au téléphone)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/utilisateurs/{id}/donnees": {"get": {"tags": ["clients"], "summary": "Export des données personnelles d'un utilisateur (droit d'accès et de portabilité), en JSON.\nPar la personne elle-même ou un admin de son organisation (`utilisateur.modifier`). Les\nnuméros sont en entier pour la personne et qui peut les voir (D60), masqués sinon. Tracé.", "operationId": "exporterDonneesPersonnelles", "parameters": [{"name": "id", "in": "path", "description": "Utilisateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Données personnelles", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/DonneesPersonnelles"}}}}, "403": {"description": "`interdit` : ni la personne ni un admin de son organisation", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/utilisateurs/{id}/effacement": {"post": {"tags": ["clients"], "summary": "Efface un utilisateur (droit à l'effacement) : compte, poste, messagerie et messages, et les\nenregistrements des appels de son poste. Restent les CDR (obligation de conservation d'un\nan, CPCE L34-1) et le journal d'audit. Par un admin de son organisation ; jamais son propre\ncompte. Refusé tant que le parcours publié mène à son poste (`poste_utilise`).", "operationId": "effacerUtilisateur", "parameters": [{"name": "id", "in": "path", "description": "Utilisateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"204": {"description": "Utilisateur effacé"}, "403": {"description": "`interdit` : permissions `utilisateur.modifier` et `poste.creer`, compte hors de portée, ou son propre compte", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`poste_utilise` : le parcours publié mène au poste", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/utilisateurs/{id}/invitation": {"post": {"tags": ["clients"], "summary": "Envoie (ou renvoie) l'invitation d'un utilisateur : un nouveau lien pour choisir son mot de\npasse, à son adresse e-mail ; le lien précédent ne vaut plus rien. Sert aussi au mot de passe\noublié. Permission `utilisateur.modifier` sur l'organisation du compte.", "operationId": "envoyerInvitation", "parameters": [{"name": "id", "in": "path", "description": "Utilisateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Invitation envoyée", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/InvitationEnvoyee"}}}}, "403": {"description": "`interdit` (permission `utilisateur.modifier`), compte inactif ou hors de portée", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`smtp_absent` : aucun serveur d'e-mails réglé par l'opérateur", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "502": {"description": "`smtp_echec` : le serveur a refusé ou n'a pas répondu (détail du serveur)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/utilisateurs/{id}/poste": {"post": {"tags": ["clients"], "summary": "Donne un poste à un compte d'un client qui n'en a pas (créé sans téléphone, ou par\nl'annuaire de l'entreprise) : mêmes règles et mêmes réglages qu'à la création d'un\ncollaborateur avec poste (extension, boîte vocale, musique d'attente du client, nom affiché =\nnom du compte). Un compte n'a qu'un poste : pour en changer, créer le nouveau collaborateur\npuis supprimer l'ancien.", "operationId": "attribuerPoste", "parameters": [{"name": "id", "in": "path", "description": "Utilisateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/NouveauPosteDuCompte"}}}, "required": true}, "responses": {"201": {"description": "Poste créé et rattaché au compte", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UtilisateurClient"}}}}, "403": {"description": "`interdit` (permission `poste.creer` sur le client du compte, ou compte hors de portée) ; `ajout_utilisateurs_non_autorise` : compte du client alors que l'opérateur ne lui laisse pas l'ajout de postes (D121) ; `licence_bloquee` : licence échue depuis plus de 30 jours (D78)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "409": {"description": "`poste_deja_attribue` : le compte a déjà un poste ; `poste_existant` : numéro pris ; `numero_de_module` : numéro interne d'un module du parcours", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}, "422": {"description": "`poste_invalide`, `poste_numero_urgence` ; `poste_hors_client` : seuls les comptes d'un client ont un poste", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/utilisateurs/{id}/second-facteur/reinitialisation": {"post": {"tags": ["clients"], "summary": "Réinitialise le second facteur d'un utilisateur (téléphone perdu, passkey égarée) : TOTP,\npasskeys et codes de secours supprimés, sessions fermées ; il en configurera un nouveau à sa\nprochaine connexion. Réservé à un admin **du niveau supérieur** (§6) : organisation\nancêtre, ou admin client pour un utilisateur simple de son client. Jamais son propre compte,\njamais par une clé d'API.", "operationId": "reinitialiserSecondFacteur", "parameters": [{"name": "id", "in": "path", "description": "Utilisateur", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"204": {"description": "Second facteur réinitialisé"}, "403": {"description": "`interdit` : pas le droit, même niveau, son propre compte ou clé d'API", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}, "security": [{"session": []}]}}, "/api/v1/webhooks/audio": {"get": {"tags": ["webhooks"], "summary": "Audio d'un message vocal, par le lien du webhook `voicemail.new` (sans session : le jeton\nsigné désigne le message, sept jours).", "operationId": "telechargerMessageVocal", "parameters": [{"name": "jeton", "in": "query", "description": "Jeton reçu dans le webhook `cdr.month`.", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "WAV (MP3 pour un message de la messagerie de repli)", "content": {"audio/wav": {"schema": {"type": "array", "items": {"type": "integer", "format": "int32", "minimum": 0}}}}}, "404": {"description": "`introuvable` : jeton invalide ou expiré, message supprimé", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}}}, "/api/v1/webhooks/cdr.csv": {"get": {"tags": ["webhooks"], "summary": "CSV d'un mois du parc, par le lien du webhook `cdr.month` (sans session : le jeton signé\ndésigne l'organisation et le mois, sept jours).", "operationId": "telechargerCdrDuMois", "parameters": [{"name": "jeton", "in": "query", "description": "Jeton reçu dans le webhook `cdr.month`.", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "CSV du mois (comme l'export du parc)", "content": {"text/csv": {"schema": {"type": "string"}}}}, "404": {"description": "`introuvable` : jeton invalide ou expiré", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}}}, "/api/v1/webhooks/enregistrement": {"get": {"tags": ["webhooks"], "summary": "Enregistrement d'un appel, par le lien du webhook `call.recorded` (sans session : le jeton\nsigné désigne l'appel, sept jours).", "operationId": "telechargerEnregistrement", "parameters": [{"name": "jeton", "in": "query", "description": "Jeton reçu dans le webhook `cdr.month`.", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "MP3 (ou WAV)", "content": {"audio/mpeg": {"schema": {"type": "array", "items": {"type": "integer", "format": "int32", "minimum": 0}}}}}, "404": {"description": "`introuvable` : jeton invalide ou expiré, enregistrement supprimé, option coupée (D111)", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Probleme"}}}}}}}}, "components": {"schemas": {"AccesMobile": {"type": "object", "description": "Application mobile activée sur un poste (sans son jeton).", "required": ["id", "nom", "identifiant", "prefixe", "cree_le", "vu_le"], "properties": {"id": {"type": "string", "format": "uuid"}, "nom": {"type": "string"}, "identifiant": {"type": "string"}, "prefixe": {"type": "string"}, "cree_le": {"type": "string", "format": "date-time"}, "vu_le": {"type": "string", "format": "date-time"}}}, "AccesSip": {"type": "object", "description": "Port et transport sur lesquels un téléphone s'inscrit.", "required": ["transport", "port"], "properties": {"transport": {"type": "string", "description": "`udp`, `tcp` ou `tls`."}, "port": {"type": "integer", "format": "int32", "minimum": 0}}}, "ActionEnAttente": {"type": "object", "description": "Écriture proposée par l'assistant, à confirmer.", "required": ["id", "outil", "description", "arguments"], "properties": {"id": {"type": "string"}, "outil": {"type": "string", "description": "Outil (`operationId` de l'API)."}, "description": {"type": "string"}, "arguments": {}}}, "ActionExportee": {"type": "object", "required": ["horodatage", "action", "resultat"], "properties": {"horodatage": {"type": "string", "format": "date-time"}, "action": {"type": "string"}, "adresse_ip": {"type": ["string", "null"]}, "resultat": {"type": "string"}}}, "ActivationMobile": {"type": "object", "description": "Réponse de l'activation : le jeton d'appareil, remis une seule fois.", "required": ["jeton_appareil", "api", "poste"], "properties": {"jeton_appareil": {"type": "string", "description": "Jeton d'appareil (`Authorization: Bearer cxmob_…`), à garder dans le stockage\nsécurisé du téléphone."}, "api": {"type": "string", "description": "Adresse de l'API de l'instance."}, "poste": {"type": "string", "description": "Numéro du poste."}}}, "AdressesAlerte": {"type": "object", "required": ["courriels"], "properties": {"courriels": {"type": "array", "items": {"type": "string"}, "description": "Adresses e-mail qui reçoivent les alertes ; vide : aucune alerte."}}}, "Affectation": {"type": "object", "required": ["numero_id"], "properties": {"numero_id": {"type": "string", "format": "uuid"}}}, "AffichageMiseEnRoute": {"type": "object", "required": ["masquee"], "properties": {"masquee": {"type": "boolean", "description": "Masque (`true`) ou réaffiche la tuile de l'accueil."}}}, "AnnonceDeposee": {"type": "object", "description": "Une annonce déposée.", "required": ["nature", "cible", "module", "taille", "modifiee_le"], "properties": {"nature": {"$ref": "#/components/schemas/Nature"}, "cible": {"type": "string", "description": "Numéro interne du module, ou E.164 pour le prédécroché d'un numéro."}, "module": {"type": "string", "description": "Identifiant du module concerné (`svi:900`)."}, "taille": {"type": "integer", "format": "int64", "description": "Taille du WAV servi, en octets.", "minimum": 0}, "modifiee_le": {"type": "string", "format": "date-time"}}}, "ApercuMateriel": {"type": "object", "description": "Fichiers produits pour un appareil fictif (mots de passe masqués).", "required": ["fichiers"], "properties": {"fichiers": {"type": "array", "items": {"$ref": "#/components/schemas/FichierApercu"}}}}, "ApercuRevalorisation": {"type": "object", "description": "Aperçu (ou bilan) d'une revalorisation : les appels dont un montant change, leurs totaux avant\net après, l'écart.", "required": ["appels", "avant", "apres", "ecart", "applique"], "properties": {"appels": {"type": "integer", "format": "int64", "description": "Appels dont un montant change.", "minimum": 0}, "avant": {"$ref": "#/components/schemas/TotauxNatures"}, "apres": {"$ref": "#/components/schemas/TotauxNatures"}, "ecart": {"$ref": "#/components/schemas/TotauxNatures", "description": "Après moins avant."}, "applique": {"type": "boolean", "description": "Les montants ont été écrits (sinon : simulation)."}}}, "Appareil": {"type": "object", "required": ["agent", "ip"], "properties": {"agent": {"type": "string", "description": "`User-Agent` de l'appareil."}, "ip": {"type": "string", "description": "Adresse vue par le moteur de téléphonie."}, "expire_dans": {"type": ["integer", "null"], "format": "int32", "description": "Secondes avant expiration de l'inscription.", "minimum": 0}}}, "AppareilMateriel": {"type": "object", "description": "Un téléphone de bureau (ou une base DECT).", "required": ["id", "mac", "modele", "profil", "nom", "lignes", "touches", "parametres", "adresse_provisionnement", "rps_possible", "redemarrage_possible"], "properties": {"id": {"type": "string", "format": "uuid"}, "mac": {"type": "string", "description": "12 chiffres hexadécimaux minuscules : l'identifiant HTTP de l'appareil."}, "modele": {"type": "string"}, "modele_nom": {"type": ["string", "null"]}, "profil": {"type": "string"}, "profil_nom": {"type": ["string", "null"]}, "nom": {"type": "string"}, "numero_de_serie": {"type": ["string", "null"]}, "lignes": {"type": "array", "items": {"$ref": "#/components/schemas/LigneAppareil"}}, "touches": {"type": "array", "items": {"$ref": "#/components/schemas/ToucheAppareil"}}, "parametres": {"type": "string", "description": "Paramètres supplémentaires de l'appareil (vides pour l'admin du client, qui ne les règle\npas)."}, "derniere_lecture": {"type": ["string", "null"], "description": "Dernière configuration lue (RFC 3339), adresse et agent de cette demande."}, "derniere_adresse": {"type": ["string", "null"]}, "dernier_agent": {"type": ["string", "null"]}, "adresse_provisionnement": {"type": "string", "description": "Adresse de provisionnement à donner à l'appareil."}, "rps_possible": {"type": "boolean", "description": "Le profil passe par le RPS Yealink (déclaration possible avec le numéro de série)."}, "rps_etat": {"type": ["string", "null"], "description": "Déclaration au RPS : `declare`, `echec` (voir `rps_message`), absente si jamais tentée."}, "rps_message": {"type": ["string", "null"], "description": "Message de YMCS après un échec."}, "redemarrage_possible": {"type": "boolean", "description": "Le profil sait redémarrer ses téléphones à distance."}}}, "AppareilMobile": {"type": "object", "description": "Appareil mobile inscrit (sans son jeton push).", "required": ["id", "plateforme", "identifiant", "version_appli", "cree_le", "vu_le"], "properties": {"id": {"type": "string", "format": "uuid"}, "plateforme": {"type": "string"}, "identifiant": {"type": "string"}, "version_appli": {"type": "string"}, "cree_le": {"type": "string", "format": "date-time"}, "vu_le": {"type": "string", "format": "date-time"}}}, "Appel": {"type": "object", "description": "Un appel du journal. Montants en millionièmes de la devise de l'instance, HT, présents selon\nle rôle et si l'appel est valorisé (sortant décroché, D59).", "required": ["id", "debut", "sens", "appelant", "appele", "duree", "decroche", "issue", "cause", "enregistre"], "properties": {"id": {"type": "string", "format": "uuid"}, "debut": {"type": "string", "format": "date-time"}, "sens": {"type": "string", "description": "`entrant`, `sortant` ou `interne`."}, "appelant": {"type": "string", "description": "E.164 (masqué selon le réglage du client) ou numéro de poste."}, "appele": {"type": "string"}, "poste": {"type": ["string", "null"]}, "nom_appelant": {"type": ["string", "null"], "description": "Nom présenté du poste appelant, quand l'appelant est un poste du client qui en a un."}, "nom_appele": {"type": ["string", "null"], "description": "Nom présenté du poste appelé, quand l'appelé est un poste du client qui en a un."}, "nom_poste": {"type": ["string", "null"], "description": "Nom présenté du poste concerné (`poste`), s'il en a un."}, "duree": {"type": "integer", "format": "int32", "description": "Secondes, de la création au raccroché."}, "decroche": {"type": "integer", "format": "int32", "description": "Secondes décrochées (accueil vocal compris, pour un entrant)."}, "issue": {"type": "string", "description": "`repondu`, `message` ou `manque` pour un entrant (D66) ; `repondu` ou `sans_reponse` sinon."}, "cause": {"type": "string"}, "destination": {"type": ["string", "null"]}, "categorie": {"type": ["string", "null"], "description": "Sortant : catégorie du numéro appelé, vue du pays du client (D124) : `fixe` (plan\nnord-américain : fixes et mobiles), `mobile`, `international`, `surtaxe`, `court`,\n`urgence` ou `speciaux` ; absente pour un entrant ou un interne."}, "secondes_facturees": {"type": ["integer", "null"], "format": "int32"}, "montant_client": {"type": ["integer", "null"], "format": "int64"}, "montant_revendeur": {"type": ["integer", "null"], "format": "int64"}, "montant_achat": {"type": ["integer", "null"], "format": "int64"}, "enregistre": {"type": "boolean", "description": "L'appel est enregistré (D62 : l'écoute est réservée au client) ; toujours faux quand\nl'option est coupée pour le client (D111), l'enregistrement restant gardé."}, "renvoi_de": {"type": ["string", "null"], "format": "uuid", "description": "Sortant passé pour un autre appel (renvoi vers l'extérieur, D104) : cet appel. Le portail\nle montre comme sa « mise en relation » ; il est facturé comme un sortant."}, "en_relation": {"type": ["integer", "null"], "format": "int32", "description": "Entrant renvoyé vers l'extérieur : secondes en relation avec le correspondant."}}}, "AppelEnCours": {"type": "object", "description": "Un appel en cours (une jambe, au sens du moteur de téléphonie).", "required": ["uuid", "client_id", "client", "direction", "appelant", "appele", "etat", "application"], "properties": {"uuid": {"type": "string", "description": "Identifiant de la jambe (`uuid_kill` pour la couper)."}, "client_id": {"type": "string", "format": "uuid"}, "client": {"type": "string"}, "direction": {"type": "string", "description": "`inbound` ou `outbound`, vu du moteur de téléphonie."}, "appelant": {"type": "string"}, "appele": {"type": "string"}, "etat": {"type": "string", "description": "`RINGING`, `ACTIVE`, `HELD`…"}, "application": {"type": "string", "description": "Application en cours (`bridge`, `ivr`, `playback`…)."}, "debut": {"type": ["string", "null"], "format": "date-time"}}}, "AppelExporte": {"type": "object", "required": ["debut", "sens", "appelant", "appele", "duree"], "properties": {"debut": {"type": "string", "format": "date-time"}, "sens": {"type": "string"}, "appelant": {"type": "string"}, "appele": {"type": "string"}, "duree": {"type": "integer", "format": "int32"}}}, "AppelsBloques": {"type": "object", "description": "Appels entrants bloqués du client.", "required": ["demarchage", "numeros"], "properties": {"demarchage": {"type": "boolean", "description": "Rejeter le démarchage commercial (plages réservées par l'ARCEP) : clients français\nseulement (D124), sans effet ailleurs."}, "numeros": {"type": "array", "items": {"$ref": "#/components/schemas/NumeroBloque"}}}}, "AppelsChiffres": {"type": "object", "required": ["actif"], "properties": {"actif": {"type": "boolean", "description": "SRTP proposé aux téléphones SIP du client (réglés en SIP TLS et SRTP)."}}}, "ApplicationAutorisee": {"type": "object", "description": "Application à laquelle le compte a donné accès.", "required": ["id", "application", "client_id", "hote", "autorisee_le"], "properties": {"id": {"type": "string", "format": "uuid", "description": "Accord (pour le révoquer)."}, "application": {"type": "string", "description": "Nom que l'application se donne."}, "client_id": {"type": "string"}, "hote": {"type": "string", "description": "Hôte de son adresse de retour."}, "autorisee_le": {"type": "string", "format": "date-time"}, "derniere_utilisation": {"type": ["string", "null"], "format": "date-time"}}}, "ApplicationTrace": {"type": "object", "description": "Une application exécutée sur l'appel.", "required": ["nom", "donnees"], "properties": {"nom": {"type": "string"}, "donnees": {"type": "string"}}}, "Attente": {"type": "object", "required": ["ext", "nom", "agent", "attente_max", "appels_max"], "properties": {"ext": {"type": "string"}, "nom": {"type": "string"}, "agent": {"type": "string", "description": "Le poste qui décroche (`100`)."}, "attente_max": {"type": "integer", "format": "int32", "description": "Secondes d'attente au plus.", "minimum": 0}, "appels_max": {"type": "integer", "format": "int32", "description": "Appels en attente au plus.", "minimum": 0}}}, "AttributionGrille": {"type": "object", "description": "Grille attribuée à un client ou à un revendeur ; absente : celle par défaut.", "properties": {"grille": {"type": ["string", "null"], "format": "uuid"}}}, "BoiteVocale": {"type": "object", "description": "Une boîte vocale et ses réglages.", "required": ["poste", "active", "courriels", "piece_jointe", "garder_apres_courriel", "transcription", "annonce", "nouveaux", "lus"], "properties": {"poste": {"type": "string", "description": "Numéro du poste, aussi numéro de la boîte."}, "active": {"type": "boolean", "description": "Un appelant peut laisser un message."}, "courriels": {"type": "array", "items": {"type": "string"}, "description": "Adresses où chaque message est envoyé ; vide : pas d'e-mail."}, "piece_jointe": {"type": "boolean", "description": "Le message part en pièce jointe."}, "garder_apres_courriel": {"type": "boolean", "description": "Le message reste dans la boîte après l'e-mail."}, "transcription": {"type": "boolean", "description": "Les messages sont transcrits (D19)."}, "annonce": {"type": "boolean", "description": "Une annonce d'accueil est déposée (sinon l'annonce par défaut)."}, "annonce_texte": {"type": ["string", "null"], "description": "Texte de l'annonce, si elle a été lue par la voix de synthèse : à reprendre pour la\nmodifier."}, "nouveaux": {"type": "integer", "format": "int64"}, "lus": {"type": "integer", "format": "int64"}}}, "BouchonGrille": {"type": "object", "description": "Prix de la ligne bouchon `*` d'une grille de vente (D110) : il remplace celle du CSV ou de la\ngrille de départ, sans marge.", "required": ["prix_minute"], "properties": {"prix_minute": {"type": "string", "description": "Prix à la minute dans la devise de l'instance, HT (`0,50`)."}, "frais": {"type": ["string", "null"], "description": "Frais de connexion dans la devise de l'instance, HT ; absents : aucun."}, "palier": {"type": ["string", "null"], "description": "`minimum/incrément` en secondes (`60/60`) ; absent : `60/60`."}}}, "Brouillon": {"type": "object", "description": "Le brouillon partagé du client.", "required": ["contenu", "modifie_le", "verification"], "properties": {"contenu": {"$ref": "#/components/schemas/Parcours"}, "version_base": {"type": ["integer", "null"], "format": "int32", "description": "Version publiée dont il part ; aucune : `null`."}, "modifie_le": {"type": "string", "format": "date-time"}, "verification": {"$ref": "#/components/schemas/Verification"}}}, "BudgetClient": {"type": "object", "description": "Budget mensuel d'un client, consommation du mois et restriction en cours.", "required": ["bloquer", "mois", "consommation"], "properties": {"montant": {"type": ["integer", "null"], "format": "int64", "description": "Montant mensuel HT au prix de vente au client, en millionièmes de la devise de\nl'instance ; absent : pas de budget."}, "bloquer": {"type": "boolean", "description": "Au seuil, restreindre les sortants aux fixes et mobiles du pays du client (sinon, seulement\nalerter)."}, "mois": {"type": "string", "description": "Mois en cours dans le fuseau du client (`AAAA-MM`)."}, "consommation": {"type": "integer", "format": "int64", "description": "Consommation sortante du mois en cours, au prix de vente au client (les montants du\njournal)."}, "restriction": {"oneOf": [{"$ref": "#/components/schemas/RestrictionBudget", "description": "Restriction en cours ; absente : aucune."}, {"type": "null"}]}}}, "CaseChaleur": {"type": "object", "description": "Appels reçus un jour de la semaine, à une heure.", "required": ["jour_semaine", "heure", "recus", "manques"], "properties": {"jour_semaine": {"type": "integer", "format": "int32", "description": "1 (lundi) à 7 (dimanche)."}, "heure": {"type": "integer", "format": "int32", "description": "0 à 23."}, "recus": {"type": "integer", "format": "int64"}, "manques": {"type": "integer", "format": "int64"}}}, "CauseEchec": {"type": "object", "description": "Une cause d'échec et son nombre d'appels.", "required": ["cause", "appels"], "properties": {"cause": {"type": "string", "description": "Cause de fin d'appel (`CALL_REJECTED`, `NORMAL_TEMPORARY_FAILURE`…)."}, "appels": {"type": "integer", "format": "int64"}}}, "Certificat": {"type": "object", "required": ["hote", "lets_encrypt_possible"], "properties": {"hote": {"type": "string", "description": "Nom d'hôte de l'instance (`KANADR_URL_PUBLIQUE`)."}, "lets_encrypt_possible": {"type": "boolean", "description": "Let's Encrypt possible : adresse publique en `https://` sur un nom de domaine."}, "servi": {"oneOf": [{"$ref": "#/components/schemas/CertificatServi", "description": "Certificat que nginx sert pour cet hôte ; absent s'il ne répond pas en HTTPS."}, {"type": "null"}]}, "demande": {"oneOf": [{"$ref": "#/components/schemas/DemandeCertificat", "description": "Dernière demande de certificat Let's Encrypt, s'il y en a eu une."}, {"type": "null"}]}}}, "CertificatServi": {"type": "object", "required": ["emetteur", "sujet", "expire_le", "autosigne"], "properties": {"emetteur": {"type": "string", "description": "Émetteur (`O=Let's Encrypt, CN=R11`)."}, "sujet": {"type": "string", "description": "Sujet (`CN=pbx.operateur.exemple`)."}, "expire_le": {"type": "string", "format": "date-time", "description": "Fin de validité."}, "autosigne": {"type": "boolean", "description": "Certificat autosigné (celui de la machine au premier démarrage)."}}}, "Changement": {"type": "object", "required": ["nature"], "properties": {"nature": {"type": "string", "description": "`poste` (inscription d'un poste) ou `appel` (appel commencé ou fini) : l'état est à relire."}}}, "ChangementEtat": {"type": "object", "required": ["etat"], "properties": {"etat": {"type": "string", "description": "`libre`, `porte_sortant` ou `resilie`. Un numéro chez un client ne passe qu'à\n`porte_sortant`, qui le retire du client comme un retrait."}}}, "ChoixNumeroPresente": {"type": "object", "properties": {"numero_id": {"type": ["string", "null"], "format": "uuid", "description": "Un numéro du client ; absent ou `null` : aucun numéro présenté."}}}, "Cle": {"type": "object", "required": ["id", "organisation_id", "nom", "role", "prefixe", "cree_le"], "properties": {"id": {"type": "string", "format": "uuid"}, "organisation_id": {"type": "string", "format": "uuid"}, "nom": {"type": "string"}, "role": {"type": "string"}, "permissions": {"type": ["array", "null"], "items": {"type": "string"}}, "prefixe": {"type": "string", "description": "Début de la clé, pour la reconnaître."}, "cree_le": {"type": "string", "format": "date-time"}, "expire_le": {"type": ["string", "null"], "format": "date-time"}, "revoquee_le": {"type": ["string", "null"], "format": "date-time"}, "derniere_utilisation": {"type": ["string", "null"], "format": "date-time"}}}, "CleCreee": {"allOf": [{"$ref": "#/components/schemas/Cle"}, {"type": "object", "required": ["secret"], "properties": {"secret": {"type": "string", "description": "La clé, à transmettre dans `Authorization: Bearer`. Elle ne sera plus affichée."}}}], "description": "Clé créée : le secret n'est donné qu'ici, une seule fois."}, "CleSsoJeton": {"type": "object", "required": ["cle", "audience"], "properties": {"cle": {"type": "string", "description": "Clé HS256 à donner à l'outil de l'opérateur ; affichée cette fois seulement."}, "audience": {"type": "string"}}}, "Client": {"type": "object", "required": ["id", "nom", "domaine", "domaine_uuid", "parent_id", "actif", "utilisateurs", "enregistrement_autorise", "ajout_utilisateurs_autorise", "pays"], "properties": {"id": {"type": "string", "format": "uuid"}, "nom": {"type": "string"}, "domaine": {"type": "string"}, "domaine_uuid": {"type": "string", "format": "uuid", "description": "Domaine SIP du client, dans le moteur de téléphonie."}, "parent_id": {"type": "string", "format": "uuid", "description": "Opérateur ou revendeur dont dépend le client."}, "actif": {"type": "boolean", "description": "`false` : client suspendu (comptes sans connexion, téléphonie arrêtée)."}, "utilisateurs": {"type": "integer", "format": "int64", "description": "Comptes du client (utilisateurs et admins, actifs ou non)."}, "enregistrement_autorise": {"type": "boolean", "description": "Enregistrement des appels autorisé par l'opérateur ou le revendeur (D111) ; coupé : ni\nréglage ni écoute dans l'espace du client."}, "ajout_utilisateurs_autorise": {"type": "boolean", "description": "L'admin du client peut ajouter des utilisateurs et des postes (D121), au choix de\nl'opérateur ou du revendeur ; coupé par défaut : seuls eux en ajoutent."}, "pays": {"type": "string", "description": "Pays du client (D124, code de `GET /pays`) : le portail lit et affiche les numéros de ses\nécrans dans son plan de numérotation, comme le serveur lit ses saisies."}}}, "ClientTableau": {"type": "object", "description": "Un client du classement : ses sortants sur la période.", "required": ["client_id", "nom", "appels", "secondes_facturees"], "properties": {"client_id": {"type": "string", "format": "uuid"}, "nom": {"type": "string"}, "appels": {"type": "integer", "format": "int64"}, "secondes_facturees": {"type": "integer", "format": "int64"}, "ventes": {"type": ["integer", "null"], "format": "int64"}}}, "Code": {"type": "object", "required": ["code"], "properties": {"code": {"type": "string", "description": "Code TOTP à 6 chiffres, ou code de secours."}}}, "CodeDeConnexion": {"type": "object", "required": ["code"], "properties": {"code": {"type": "string", "description": "Code TOTP à 6 chiffres, ou code de secours."}, "confiance": {"type": "boolean", "description": "Faire confiance à ce navigateur pendant 30 jours (appareil de confiance, D53, D76) : plus\nde code, et session de 30 jours ; cookie `appareil` posé avec la session."}}}, "CodesDeSecours": {"type": "object", "description": "Codes de secours, affichés une seule fois.", "required": ["codes_de_secours"], "properties": {"codes_de_secours": {"type": "array", "items": {"type": "string"}}}}, "CompteEquipe": {"type": "object", "required": ["id", "courriel", "nom", "role", "actif"], "properties": {"id": {"type": "string", "format": "uuid"}, "courriel": {"type": "string"}, "nom": {"type": "string"}, "role": {"type": "string"}, "actif": {"type": "boolean"}, "invitation_envoyee": {"type": ["boolean", "null"], "description": "À la création seulement : l'invitation est-elle partie par e-mail ? `false` sans serveur\nd'e-mails réglé, ou si le serveur l'a refusée (à renvoyer par\n`POST /utilisateurs/{id}/invitation`)."}}}, "CompteExporte": {"type": "object", "required": ["id", "nom", "courriel", "role", "actif", "organisation", "cree_le"], "properties": {"id": {"type": "string", "format": "uuid"}, "nom": {"type": "string"}, "courriel": {"type": "string"}, "role": {"type": "string"}, "actif": {"type": "boolean"}, "organisation": {"type": "string"}, "cree_le": {"type": "string", "format": "date-time"}}}, "Conference": {"type": "object", "required": ["ext", "nom", "code_participant", "code_moderateur", "attendre_moderateur", "participants_max"], "properties": {"ext": {"type": "string"}, "nom": {"type": "string"}, "code_participant": {"type": "string"}, "code_moderateur": {"type": "string"}, "attendre_moderateur": {"type": "boolean", "description": "Les participants attendent le modérateur."}, "participants_max": {"type": "integer", "format": "int32", "minimum": 0}}}, "Confirmation": {"type": "object", "required": ["id", "accepter"], "properties": {"id": {"type": "string", "description": "Appel d'outil en attente (`tool_use`)."}, "accepter": {"type": "boolean"}}}, "Consommation": {"type": "object", "required": ["mois", "estimation", "jours", "jours_du_mois", "clients"], "properties": {"mois": {"type": "string", "description": "`AAAA-MM`."}, "estimation": {"type": "boolean", "description": "Mois en cours : forfaits estimés au prorata des jours écoulés et des utilisateurs actuels."}, "jours": {"type": "integer", "format": "int32", "description": "Jours du mois comptés pour les forfaits (écoulés, aujourd'hui compris, pour le mois en\ncours).", "minimum": 0}, "jours_du_mois": {"type": "integer", "format": "int32", "description": "Jours du mois.", "minimum": 0}, "clients": {"type": "array", "items": {"$ref": "#/components/schemas/ConsommationClient"}}}}, "ConsommationClient": {"type": "object", "description": "Consommation d'un client sur le mois. Montants en millionièmes de la devise de l'instance, HT ; absents quand le\nniveau de grille ne s'applique pas ou n'est pas visible.", "required": ["client_id", "nom", "appels", "secondes_facturees", "utilisateurs", "marge"], "properties": {"client_id": {"type": "string", "format": "uuid"}, "nom": {"type": "string"}, "revendeur_id": {"type": ["string", "null"], "format": "uuid", "description": "Revendeur du client, s'il en a un."}, "appels": {"type": "integer", "format": "int64", "description": "Appels sortants décrochés valorisés (D59)."}, "secondes_facturees": {"type": "integer", "format": "int64"}, "montant_achat": {"type": ["integer", "null"], "format": "int64", "description": "Prix d'achat de l'opérateur ; l'opérateur seul le voit."}, "montant_revendeur": {"type": ["integer", "null"], "format": "int64", "description": "Vente de l'opérateur au revendeur."}, "montant_client": {"type": ["integer", "null"], "format": "int64", "description": "Vente au client."}, "utilisateurs": {"type": "integer", "format": "int64", "description": "Utilisateurs comptés pour les forfaits (D71) : actuels pour le mois en cours, sinon ceux\ndu dernier relevé de licence du mois (actuels s'il n'y en a pas)."}, "forfait_revendeur": {"type": ["integer", "null"], "format": "int64", "description": "Forfait indicatif vendu par l'opérateur au revendeur pour ce client, sur le mois (D120) ;\nabsent : client direct ou aucun forfait."}, "forfait_client": {"type": ["integer", "null"], "format": "int64", "description": "Forfait indicatif vendu au client, sur le mois ; absent : aucun forfait."}, "marge": {"type": "integer", "format": "int64", "description": "Marge indicative de l'organisation sur le client : forfaits et appels vendus moins\nforfaits et appels achetés (un montant absent compte pour zéro)."}}}, "ContactPersonnel": {"type": "object", "description": "Un contact personnel.", "required": ["id", "nom", "numeros", "modifie_le"], "properties": {"id": {"type": "string", "format": "uuid"}, "nom": {"type": "string"}, "entreprise": {"type": ["string", "null"]}, "numeros": {"type": "array", "items": {"type": "string"}, "description": "E.164, dans l'ordre donné."}, "modifie_le": {"type": "string", "format": "date-time"}}}, "ContactRepertoire": {"type": "object", "description": "Une entrée du répertoire commun.", "required": ["id", "nom", "numero"], "properties": {"id": {"type": "string", "format": "uuid"}, "nom": {"type": "string"}, "numero": {"type": "string", "description": "E.164."}}}, "ContactTelephone": {"type": "object", "description": "Un contact du softphone.", "required": ["id", "nom", "numero", "poste", "modifiable"], "properties": {"id": {"type": "string"}, "nom": {"type": "string"}, "numero": {"type": "string", "description": "Numéro composé : un poste, ou un numéro en E.164."}, "poste": {"type": "boolean", "description": "`true` : un autre poste du client ; `false` : son répertoire commun."}, "modifiable": {"type": "boolean", "description": "Entrée du répertoire que le compte peut modifier ou supprimer : toutes pour l'admin du\nclient, celles qu'il a ajoutées pour un collaborateur (répertoire ouvert)."}}}, "ContenuProfil": {"type": "object", "description": "Contenu d'un profil : ce que l'opérateur modifie et que l'historique garde.", "required": ["modeles", "fichiers", "gabarits", "resynchronisation", "parametres", "premiere_touche", "combines", "tls"], "properties": {"modeles": {"type": "array", "items": {"$ref": "#/components/schemas/ModeleMateriel"}}, "fichiers": {"type": "array", "items": {"$ref": "#/components/schemas/FichierServi"}}, "gabarits": {"type": "object", "description": "Gabarits (syntaxe Jinja) par clé ; variables documentées dans le guide de l'opérateur.", "additionalProperties": {"type": "string"}, "propertyNames": {"type": "string"}}, "resynchronisation": {"type": "string", "description": "Événement du NOTIFY de resynchronisation (`check-sync`, `resync`)."}, "redemarrage": {"type": "string", "description": "Événement du NOTIFY de redémarrage (`check-sync;reboot=true`) ; vide : pas de\nredémarrage à distance."}, "parametres": {"type": "string", "description": "Paramètres supplémentaires du profil, une ligne `clé = valeur`."}, "premiere_touche": {"type": "integer", "format": "int32", "description": "Première touche programmable libre ; 0 sans touches.", "minimum": 0}, "combines": {"type": "boolean", "description": "Une ligne d'appareil désigne un combiné (base DECT)."}, "tls": {"type": "boolean", "description": "Les modèles savent faire du SIP en TLS (appels chiffrés, D92)."}}}, "Conversation": {"type": "object", "required": ["messages"], "properties": {"messages": {"type": "array", "items": {}, "description": "Messages de la conversation, au format de l'API Messages d'Anthropic (rôles `user` et\n`assistant`), tels que renvoyés par l'appel précédent, plus le nouveau message."}, "confirmation": {"oneOf": [{"$ref": "#/components/schemas/Confirmation", "description": "Réponse à l'écriture en attente."}, {"type": "null"}]}}}, "DebutOidc": {"type": "object", "required": ["courriel"], "properties": {"courriel": {"type": "string", "description": "Adresse saisie sur la page de connexion."}}}, "DemandeActivation": {"type": "object", "description": "Ce que l'application envoie pour s'activer.", "required": ["jeton", "identifiant"], "properties": {"jeton": {"type": "string", "description": "Jeton du lien d'installation (paramètre `jeton` du QR code)."}, "identifiant": {"type": "string", "description": "Identifiant stable de l'installation (le même qu'à l'inscription du jeton push)."}, "nom": {"type": "string", "description": "Nom de l'appareil, montré dans la fiche utilisateur (« iPhone de Paul »)."}}}, "DemandeApercu": {"type": "object", "description": "Aperçu d'un profil, enregistré ou en cours d'écriture.", "required": ["modele"], "properties": {"profil": {"type": ["string", "null"], "description": "Profil enregistré ; ignoré si `contenu` est donné."}, "contenu": {"oneOf": [{"$ref": "#/components/schemas/ContenuProfil", "description": "Contenu pas encore enregistré."}, {"type": "null"}]}, "modele": {"type": "string", "description": "Code du modèle de l'appareil fictif."}}}, "DemandeCertificat": {"type": "object", "required": ["etat"], "properties": {"etat": {"type": "string", "description": "`en_attente` (demande écrite, service pas encore lancé), `en_cours`, `reussi` ou `echec`."}, "debut": {"type": ["string", "null"], "format": "date-time", "description": "Début de la dernière exécution."}, "fin": {"type": ["string", "null"], "format": "date-time", "description": "Fin de la dernière exécution."}, "journal": {"type": ["string", "null"], "description": "Fin du journal de certbot (diagnostic d'un échec)."}}}, "DemandeCle": {"type": "object", "required": ["nom", "role"], "properties": {"nom": {"type": "string", "description": "Usage de la clé (ex. « CRM », « facturation »)."}, "role": {"type": "string", "description": "Rôle prédéfini, du niveau de l'organisation (`admin_client`, `utilisateur`…)."}, "permissions": {"type": ["array", "null"], "items": {"type": "string"}, "description": "Liste blanche de permissions (`client.lire`…) ; absente : toutes celles du rôle."}, "expire_le": {"type": ["string", "null"], "format": "date-time", "description": "Expiration (RFC 3339), facultative."}}}, "DemandeInstallation": {"type": "object", "properties": {"courriel": {"type": ["string", "null"], "description": "Adresse qui reçoit le lien ; absente : celle du titulaire du poste."}}}, "DemandeOauth": {"type": "object", "description": "Demande d'autorisation d'une application, présentée à l'utilisateur avant son accord.", "required": ["id", "application", "client_id", "hote", "boucle_locale", "portee"], "properties": {"id": {"type": "string", "format": "uuid"}, "application": {"type": "string", "description": "Nom que l'application se donne : déclaré par elle, non vérifié."}, "client_id": {"type": "string", "description": "Identifiant du client : `cxcl_…` (enregistré), ou l'adresse de son document."}, "hote": {"type": "string", "description": "Hôte qui recevra l'accès, tel que la redirection le lira : celui de l'assistant attendu\n(`claude.ai`, `chatgpt.com`…)."}, "hote_du_client": {"type": ["string", "null"], "description": "Client décrit par un document : l'hôte qui le publie, seule identité vérifiée."}, "boucle_locale": {"type": "boolean", "description": "Retour vers cet ordinateur même (application installée, comme Claude Code) : à\nn'accepter que si l'on vient de la lancer."}, "portee": {"type": "string", "description": "`mcp`, et `offline_access` si l'application reste connectée sans redemander."}}}, "DemandeOubli": {"type": "object", "required": ["courriel"], "properties": {"courriel": {"type": "string"}}}, "DemandePcap": {"type": "object", "required": ["messages"], "properties": {"messages": {"type": "array", "items": {"$ref": "#/components/schemas/MessagePcap"}, "description": "Messages, dans l'ordre (ceux des lignes `sip` d'une capture)."}}}, "DemandePublication": {"type": "object", "properties": {"note": {"type": "string", "description": "Note de version, libre."}}}, "DemandeRevalorisation": {"type": "object", "description": "Période d'un recalcul, en jours du fuseau du client, et son application.", "required": ["du"], "properties": {"du": {"type": "string", "format": "date", "description": "Premier jour (`AAAA-MM-JJ`), dès minuit au fuseau du client."}, "au": {"type": ["string", "null"], "format": "date", "description": "Dernier jour, inclus ; absent : jusqu'à maintenant."}, "appliquer": {"type": "boolean", "description": "Écrit les montants recalculés ; absent ou faux : aperçu seul."}}}, "DepuisGrille": {"type": "object", "description": "Grille calculée depuis une autre, prix et frais majorés d'une marge.", "required": ["grille", "marge"], "properties": {"grille": {"type": "string", "format": "uuid"}, "marge": {"type": "integer", "format": "int32", "description": "Marge en pour cent (35 : prix × 1,35), arrondie au millionième supérieur.", "minimum": 0}}}, "Destination": {"type": "object", "properties": {"poste": {"type": ["string", "null"], "description": "Poste du client ; absent ou `null` : le numéro n'est plus routé."}}}, "DestinationBloquee": {"type": "object", "required": ["prefixe"], "properties": {"prefixe": {"type": "string", "description": "Préfixe E.164 (`+882`, `+3389`)."}, "description": {"type": ["string", "null"]}}}, "DestinationTableau": {"type": "object", "description": "Sortants décrochés vers une catégorie de numéros.", "required": ["categorie", "appels", "secondes_facturees"], "properties": {"categorie": {"type": "string", "description": "Catégorie vue du pays du client qui a appelé (D124) : `fixe` (plan nord-américain : fixes\net mobiles), `mobile`, `international`, `surtaxe`, `court` (numéro court), `urgence` ou\n`speciaux` (gratuits, coûts partagés…)."}, "appels": {"type": "integer", "format": "int64"}, "secondes_facturees": {"type": "integer", "format": "int64"}, "ventes": {"type": ["integer", "null"], "format": "int64"}}}, "DeviseInstance": {"type": "object", "description": "Devise de l'instance.", "required": ["devise", "devises", "modifiable"], "properties": {"devise": {"type": "string", "description": "Code ISO 4217 : `EUR` (par défaut), `CHF`, `GBP`, `USD` ou `CAD`. Tous les montants de\nl'API sont en millionièmes de cette devise."}, "devises": {"type": "array", "items": {"type": "string"}, "description": "Devises prises en charge, dans l'ordre des listes du portail."}, "modifiable": {"type": "boolean", "description": "Faux dès qu'une grille tarifaire existe ou qu'un appel a été valorisé : la devise ne\nchange plus (pas de conversion des montants)."}}}, "Diff": {"type": "object", "description": "Modules ajoutés, retirés ou modifiés (contenu ou sorties), par identifiant, triés.", "required": ["ajoutes", "retires", "modifies"], "properties": {"ajoutes": {"type": "array", "items": {"type": "string"}}, "retires": {"type": "array", "items": {"type": "string"}}, "modifies": {"type": "array", "items": {"type": "string"}}}}, "DifferenceGabarit": {"type": "object", "description": "Différences d'un gabarit.", "required": ["gabarit", "lignes"], "properties": {"gabarit": {"type": "string"}, "lignes": {"type": "array", "items": {"$ref": "#/components/schemas/LigneDifferenceProfil"}}}}, "DifferencesProfil": {"type": "object", "description": "Différences entre une copie et la version livrée actuelle de son profil d'origine.", "required": ["origine", "origine_version", "version_livree", "nouvelle_version", "gabarits"], "properties": {"origine": {"type": "string"}, "origine_version": {"type": "integer", "format": "int32", "minimum": 0}, "version_livree": {"type": "integer", "format": "int32", "minimum": 0}, "nouvelle_version": {"type": "boolean"}, "gabarits": {"type": "array", "items": {"$ref": "#/components/schemas/DifferenceGabarit"}}}}, "Disposition": {"type": "object", "required": ["positions"], "properties": {"positions": {"type": "object", "description": "Position de chaque module déplacé à la main, par identifiant (`svi:900`) ; les autres sont\nplacés automatiquement.", "additionalProperties": {"$ref": "#/components/schemas/Position"}, "propertyNames": {"type": "string"}}}}, "DispositionAccueil": {"type": "object", "description": "Disposition de l'accueil d'un espace.", "properties": {"instances": {"type": ["array", "null"], "items": {"$ref": "#/components/schemas/InstanceAccueil"}, "description": "Instances dans l'ordre d'affichage ; absent : la disposition par défaut."}}}, "Domaines": {"type": "object", "required": ["hote", "adresses"], "properties": {"hote": {"type": "string", "description": "Nom d'hôte de l'instance (`KANADR_URL_PUBLIQUE`)."}, "adresses": {"type": "array", "items": {"type": "string"}, "description": "Adresses IPv4 et IPv6 que le DNS donne pour cet hôte (vide : il ne résout pas)."}, "suffixe": {"type": ["string", "null"], "description": "Suffixe des domaines clients (D108), s'il est réglé."}, "generique": {"type": ["array", "null"], "items": {"type": "string"}, "description": "Adresses que le DNS donne pour un nom quelconque sous le suffixe (enregistrement\ngénérique `*.<suffixe>`) ; vide : pas d'enregistrement générique. Absent sans suffixe."}}}, "DonneesPersonnelles": {"type": "object", "description": "Données personnelles d'un utilisateur.", "required": ["exporte_le", "compte", "sessions", "actions", "appels", "messages", "applications", "contacts", "favoris"], "properties": {"exporte_le": {"type": "string", "format": "date-time"}, "compte": {"$ref": "#/components/schemas/CompteExporte"}, "poste": {"type": ["string", "null"]}, "sessions": {"type": "array", "items": {"$ref": "#/components/schemas/SessionExportee"}}, "actions": {"type": "array", "items": {"$ref": "#/components/schemas/ActionExportee"}, "description": "Ses actions au journal d'audit (connexions comprises), les 500 dernières."}, "appels": {"type": "array", "items": {"$ref": "#/components/schemas/AppelExporte"}, "description": "Appels de son poste, douze derniers mois."}, "messages": {"type": "array", "items": {"$ref": "#/components/schemas/MessageExporte"}}, "applications": {"type": "array", "items": {"$ref": "#/components/schemas/ApplicationAutorisee"}, "description": "Applications auxquelles il a donné accès (OAuth, serveur MCP), en vigueur."}, "contacts": {"type": "array", "items": {"$ref": "#/components/schemas/ContactPersonnel"}, "description": "Ses contacts personnels du softphone."}, "favoris": {"type": "array", "items": {"$ref": "#/components/schemas/Favori"}, "description": "Ses favoris du softphone, dans l'ordre."}}}, "DuplicationProfil": {"type": "object", "description": "Copie d'un profil (livré ou déjà copié).", "required": ["source", "nom"], "properties": {"source": {"type": "string", "description": "Profil copié : identifiant d'un profil livré ou uuid d'une copie."}, "nom": {"type": "string"}}}, "Durees": {"type": "object", "description": "Durées réglées sur une organisation ; `null` : celle du niveau au-dessus.", "properties": {"enregistrements_jours": {"type": ["integer", "null"], "format": "int32"}, "messages_jours": {"type": ["integer", "null"], "format": "int32"}, "cdr_jours": {"type": ["integer", "null"], "format": "int32"}}}, "EchecEnregistrement": {"type": "object", "description": "Refus d'enregistrement d'un trunk par son fournisseur.", "required": ["code", "motif", "le"], "properties": {"code": {"type": "integer", "format": "int32", "description": "Code SIP (403, 408…).", "minimum": 0}, "motif": {"type": "string", "description": "Motif donné avec le code (`Forbidden`…), tel quel."}, "le": {"type": "string", "format": "date-time"}}}, "EchecEnvoi": {"type": "object", "description": "Échec d'un envoi : un code stable, traduit par le portail (D81), et un détail technique sans\nphrase (code HTTP, message de la bibliothèque réseau).", "required": ["code"], "properties": {"code": {"type": "string", "description": "`pas_https`, `identifiants`, `port`, `hote`, `adresse_privee` (adresse refusée), `dns`\n(l'hôte ne résout pas), `reseau` (connexion, délai), `http` (réponse hors 2xx)."}, "detail": {"type": ["string", "null"]}}}, "Enregistrement": {"type": "object", "description": "Réglage d'enregistrement d'un poste (D103).", "required": ["actif"], "properties": {"actif": {"type": "boolean", "description": "Tous les appels du poste, reçus, émis et internes, sont enregistrés."}}}, "EnregistrementAppel": {"type": "object", "description": "Un enregistrement d'appel.", "required": ["id", "debut", "sens", "appelant", "appele", "duree"], "properties": {"id": {"type": "string", "format": "uuid", "description": "Identifiant de l'appel (CDR)."}, "debut": {"type": "string", "format": "date-time"}, "sens": {"type": "string"}, "appelant": {"type": "string"}, "appele": {"type": "string"}, "poste": {"type": ["string", "null"]}, "duree": {"type": "integer", "format": "int32", "description": "Durée de l'enregistrement, en secondes."}}}, "EntreeAudit": {"type": "object", "description": "Une action du journal.", "required": ["rang", "horodatage", "acteur_type", "acteur", "action", "canal", "resultat", "details"], "properties": {"rang": {"type": "integer", "format": "int64", "description": "Ordre d'insertion (pagination)."}, "horodatage": {"type": "string", "format": "date-time"}, "acteur_type": {"type": "string", "description": "`utilisateur`, `cle_api`, `systeme` ou `cli`."}, "acteur": {"type": "string"}, "organisation_id": {"type": ["string", "null"], "format": "uuid"}, "organisation": {"type": ["string", "null"]}, "action": {"type": "string"}, "cible_type": {"type": ["string", "null"]}, "cible_id": {"type": ["string", "null"]}, "canal": {"type": "string"}, "adresse_ip": {"type": ["string", "null"]}, "resultat": {"type": "string"}, "details": {}}}, "Envoi": {"type": "object", "description": "Un envoi récent, pour le diagnostic.", "required": ["evenement", "objet", "tentatives", "abandonne"], "properties": {"evenement": {"type": "string"}, "objet": {"type": "string"}, "tentatives": {"type": "integer", "format": "int32"}, "livre_le": {"type": ["string", "null"], "format": "date-time"}, "abandonne": {"type": "boolean"}, "derniere_erreur": {"oneOf": [{"$ref": "#/components/schemas/EchecEnvoi"}, {"type": "null"}]}}}, "Erreur": {"type": "object", "description": "Erreur de validation : un code stable (traduit dans le portail, D81) et ce qu'elle concerne,\nsans texte dans une langue.", "required": ["code", "objets"], "properties": {"code": {"type": "string"}, "objets": {"type": "array", "items": {"type": "string"}, "description": "Modules (`groupe:600`), liens, sorties ou valeurs en cause."}}}, "ErreurGabaritMateriel": {"type": "object", "description": "Erreur d'un gabarit, avec sa position.", "required": ["gabarit", "message"], "properties": {"gabarit": {"type": "string"}, "message": {"type": "string"}, "ligne": {"type": ["integer", "null"], "minimum": 0}, "colonne": {"type": ["integer", "null"], "minimum": 0}}}, "EssaiSmtp": {"type": "object", "required": ["destinataire"], "properties": {"destinataire": {"type": "string", "description": "Adresse qui reçoit l'e-mail d'essai."}}}, "EssaiSynthese": {"type": "object", "properties": {"langue": {"type": ["string", "null"], "description": "Langue de la phrase et de la voix essayées : `fr` (par défaut) ou `en`."}}}, "EssaiTranscription": {"type": "object", "required": ["texte"], "properties": {"texte": {"type": "string", "description": "Texte rendu par le service pour une seconde de silence (souvent vide)."}}}, "EssaiVoixClient": {"type": "object", "properties": {"voix": {"type": ["string", "null"], "description": "Voix à écouter, parmi `…/voix/disponibles` ; absente : celle qui lit les annonces du\nclient."}}}, "EtapeMiseEnRoute": {"type": "object", "required": ["etape", "etat"], "properties": {"etape": {"type": "string", "description": "`langue`, `identite`, `domaines`, `certificat`, `emails`, `reseau`, `fournisseur`,\n`numeros` ou `premier_client`."}, "etat": {"type": "string", "description": "`a_faire`, `fait` ou `passe` (réglé dans l'assistant)."}, "constate": {"type": ["boolean", "null"], "description": "Constat tiré des réglages : `true` si ce que l'étape règle existe déjà (langue ou fuseau\nde l'opérateur choisis, marque, serveur d'e-mails, profil de trunk, numéro, client) ;\nabsent quand rien ne se constate sans test (domaines, certificat, réseau : voir leurs\nroutes)."}}}, "EtapeTrace": {"type": "object", "description": "Une étape du chemin d'un appel dans le dialplan.", "required": ["contexte", "numero", "extension"], "properties": {"contexte": {"type": "string", "description": "`public` (arrivée par un trunk) ou le domaine du client."}, "numero": {"type": "string"}, "extension": {"type": "string", "description": "Extension du dialplan qui a pris l'appel (`DID-…`, `Accueil`…)."}}}, "EtatAssistance": {"type": "object", "properties": {"ouvert_jusqu_a": {"type": ["string", "null"], "format": "date-time", "description": "Fin de l'accès s'il est ouvert ; absent s'il est fermé."}}}, "EtatAssistant": {"type": "object", "description": "L'assistant pour le compte connecté.", "required": ["disponible", "budget_atteint"], "properties": {"disponible": {"type": "boolean", "description": "Réglé et activé par l'opérateur (D94)."}, "budget_atteint": {"type": "boolean", "description": "Budget du mois atteint (instance ou client) : en pause jusqu'au mois suivant."}}}, "EtatConnexion": {"type": "object", "description": "Résultat d'une étape de connexion.", "required": ["etape", "utilisateur"], "properties": {"etape": {"type": "string", "description": "`connecte` ; `second_facteur` (code TOTP ou de secours attendu sur\n`/connexion/second-facteur`) ; `inscription_second_facteur` (second facteur obligatoire à\nconfigurer sur `/second-facteur/totp` avant tout autre accès)."}, "utilisateur": {"$ref": "#/components/schemas/Moi"}}}, "EtatHoraires": {"type": "object", "description": "État d'une grille horaire du parcours publié, à l'heure du client (son fuseau, D81).", "required": ["ext", "nom", "ouvert"], "properties": {"ext": {"type": "string", "description": "Numéro interne de la grille (`800`)."}, "nom": {"type": "string"}, "ouvert": {"type": "boolean"}, "jusqu_a": {"type": ["string", "null"], "description": "Fin de la plage en cours, si ouvert (`AAAA-MM-JJTHH:MM`, heure du client)."}, "reouverture": {"type": ["string", "null"], "description": "Prochaine ouverture dans les quinze jours, si fermé (`AAAA-MM-JJTHH:MM`, heure du client)."}}}, "EtatLicence": {"type": "object", "description": "État de la licence de l'éditeur (D78), pour le portail.", "required": ["etat", "jours", "lecture_seule_le"], "properties": {"etat": {"type": "string", "description": "`valide`, `echue` (dans la tolérance) ou `bloquee` (instance en lecture seule pour\nl'administration ; la téléphonie continue)."}, "jusqu_au": {"type": ["string", "null"], "format": "date", "description": "Dernier jour de validité ; absent : aucune licence reçue."}, "jours": {"type": "integer", "format": "int64", "description": "Jours restants (`valide`) ou écoulés depuis la fin (`echue`, `bloquee`)."}, "lecture_seule_le": {"type": "string", "format": "date", "description": "Premier jour de lecture seule (`AAAA-MM-JJ`) : le lendemain des 30 jours de tolérance\nqui suivent la fin de la licence (ou, sans licence reçue, la création de l'instance)."}, "utilisateurs_max": {"type": ["integer", "null"], "format": "int64", "description": "Nombre d'utilisateurs prévu au contrat, s'il est indiqué."}}}, "EtatParcours": {"type": "object", "description": "Parcours d'un client : la version servie et le brouillon en cours.", "required": ["pays", "feries"], "properties": {"publie": {"oneOf": [{"$ref": "#/components/schemas/VersionParcours"}, {"type": "null"}]}, "brouillon": {"oneOf": [{"$ref": "#/components/schemas/Brouillon"}, {"type": "null"}]}, "pays": {"type": "string", "description": "Pays du client (D124) : celui des numéros externes et des jours fériés."}, "feries": {"type": "array", "items": {"$ref": "#/components/schemas/FerieDuPays"}, "description": "Jours fériés que proposent les grilles horaires du client (ceux de son pays), dans\nl'ordre de l'année."}}}, "EtatPoste": {"type": "object", "required": ["poste", "inscrit", "appareils"], "properties": {"poste": {"type": "string"}, "nom": {"type": ["string", "null"], "description": "Nom affiché du poste."}, "inscrit": {"type": "boolean", "description": "Inscrit maintenant (au moins un appareil)."}, "appareils": {"type": "array", "items": {"$ref": "#/components/schemas/Appareil"}, "description": "Appareils inscrits maintenant."}, "derniere_inscription": {"type": ["string", "null"], "description": "Dernière inscription vue (RFC 3339), même si le poste est hors ligne depuis."}, "numero_presente": {"type": ["string", "null"], "description": "Numéro présenté à l'extérieur, tel qu'enregistré."}}}, "Favori": {"type": "object", "description": "Un favori, dans l'ordre choisi.", "required": ["genre", "reference"], "properties": {"genre": {"$ref": "#/components/schemas/GenreFavori"}, "reference": {"type": "string", "description": "Identifiant du contact : celui de `/moi/telephone/contacts` (commun) ou d'un contact\npersonnel."}}}, "FerieDuPays": {"type": "object", "description": "Un jour férié proposé dans les grilles horaires.", "required": ["code", "par_defaut"], "properties": {"code": {"type": "string", "description": "Code enregistré dans `feries_fermes` (`01-01`, `lundi_paques`, `thanksgiving`…)."}, "par_defaut": {"type": "boolean", "description": "Coché à la création d'une grille."}, "date": {"type": ["string", "null"], "description": "Jour chômé cette année (`AAAA-MM-JJ`), report d'un week-end compris."}, "date_suivante": {"type": ["string", "null"], "description": "Jour chômé l'an prochain (`AAAA-MM-JJ`)."}}}, "FichierApercu": {"type": "object", "description": "Un fichier de l'aperçu : son contenu, ou l'erreur du gabarit.", "required": ["motif", "gabarit"], "properties": {"motif": {"type": "string"}, "gabarit": {"type": "string"}, "contenu": {"type": ["string", "null"]}, "erreur": {"oneOf": [{"$ref": "#/components/schemas/ErreurGabaritMateriel"}, {"type": "null"}]}}}, "FichierLicence": {"type": "object", "description": "Licence de l'éditeur, telle qu'il la remet (fichier JSON).", "required": ["contenu", "signature"], "properties": {"contenu": {"type": "string", "description": "Texte JSON de la licence, signé tel quel."}, "signature": {"type": "string", "description": "Signature Ed25519 de l'éditeur (hexadécimal)."}}}, "FichierServi": {"type": "object", "description": "Un fichier que les téléphones du profil demandent.", "required": ["motif", "gabarit", "type_contenu"], "properties": {"motif": {"type": "string", "description": "Nom demandé, avec `{mac}` (celle de l'appareil authentifié) et `{chiffres}` ; une barre\noblique au plus."}, "gabarit": {"type": "string", "description": "Gabarit qui le produit."}, "type_contenu": {"type": "string", "description": "Type MIME servi ; un type XML échappe les valeurs."}}}, "FinAuthentification": {"type": "object", "required": ["reponse"], "properties": {"reponse": {"description": "Résultat de `navigator.credentials.get()`, sérialisé (binaires en base64url)."}, "confiance": {"type": "boolean", "description": "Faire confiance à ce navigateur, comme `confiance` de `/connexion/second-facteur`."}}}, "FinInscription": {"type": "object", "required": ["nom", "reponse"], "properties": {"nom": {"type": "string", "description": "Nom donné à la passkey (« Ordinateur du bureau »)."}, "reponse": {"description": "Résultat de `navigator.credentials.create()`, sérialisé (binaires en base64url)."}}}, "Fonctions": {"type": "object", "required": ["revendeurs", "assistant"], "properties": {"revendeurs": {"type": "boolean", "description": "Revendeurs : menu, création, grilles de vente au revendeur."}, "assistant": {"type": "boolean", "description": "Assistant IA : menu, réglage de la clé et des budgets, conversations."}, "messagerie": {"type": "boolean", "description": "Messagerie vocale : boîtes des postes, menu et réglages, dépôt et consultation par\ntéléphone, module de messagerie du parcours. Absente de la demande : activée."}, "appli_mobile": {"type": "boolean", "description": "Application mobile maison, prototype (D117) : QR code d'installation dans la fiche\nutilisateur, jetons d'appareil. Absente de la demande : coupée."}}}, "Forfait": {"type": "object", "description": "Forfait mensuel indicatif.", "required": ["mode", "montant"], "properties": {"mode": {"$ref": "#/components/schemas/ModeForfait"}, "montant": {"type": "integer", "format": "int64", "description": "Montant mensuel HT en millionièmes de la devise de l'instance (par utilisateur ou par\nclient), de 0 à 100 000 dans cette devise."}}}, "ForfaitsClient": {"type": "object", "description": "Forfaits indicatifs d'un client, aux deux niveaux de vente.", "required": ["utilisateurs", "vente_client"], "properties": {"utilisateurs": {"type": "integer", "format": "int64", "description": "Utilisateurs du client : comptes actifs d'un client actif, comme la licence (D71)."}, "vente_revendeur": {"oneOf": [{"$ref": "#/components/schemas/NiveauForfait", "description": "Vente de l'opérateur au revendeur pour ce client ; absente pour un client direct."}, {"type": "null"}]}, "vente_client": {"$ref": "#/components/schemas/NiveauForfait", "description": "Vente au client."}}}, "Format": {"type": "object", "description": "Format des numéros attendu par le fournisseur (D38). Format national : `national`,\n`tel_que_compose`, `national`, PAI sur le domaine ; format E.164 : `e164`, `plus`, `e164`, PAI\nsur l'IP publique de la plateforme.", "required": ["appele_national", "appele_international", "numero_presente"], "properties": {"pays": {"type": "string", "description": "Pays du fournisseur (D124), celui de sa forme nationale : code de `GET /pays` ; `FR`\npar défaut."}, "appele_national": {"type": "string", "description": "Appelé du pays du fournisseur : `national` (`0…` en France), `e164` (`+33…`) ou\n`e164_sans_plus` (`33…`)."}, "appele_international": {"type": "string", "description": "Appelé international : `prefixe_00`, `plus` ou `tel_que_compose`."}, "numero_presente": {"type": "string", "description": "Numéro présenté : `national`, `e164` ou `e164_sans_plus`."}, "hote_pai": {"type": ["string", "null"], "description": "Hôte du P-Asserted-Identity ; absent : le domaine du client."}}}, "FuseauOrganisation": {"type": "object", "required": ["fuseau"], "properties": {"fuseau": {"type": "string", "description": "Nom IANA (`Europe/Paris`, `America/Martinique`…), parmi `GET /fuseaux`."}}}, "Garde": {"type": "object", "required": ["reglages", "bannies"], "properties": {"reglages": {"$ref": "#/components/schemas/ReglagesGarde"}, "bannies": {"type": "array", "items": {"$ref": "#/components/schemas/IpBannie"}, "description": "Bannissements en cours."}}}, "GenreFavori": {"type": "string", "description": "Nature d'un favori.", "enum": ["commun", "personnel"]}, "Grille": {"type": "object", "required": ["ext", "nom", "semaine", "feries_fermes", "fermetures"], "properties": {"ext": {"type": "string"}, "nom": {"type": "string"}, "semaine": {"type": "array", "items": {"type": ["string", "null"]}, "description": "Une plage `HH:MM-HH:MM` par jour (lundi d'abord), `None` : fermé."}, "pause": {"type": ["array", "null"], "items": false, "prefixItems": [{"type": "integer", "format": "int32", "minimum": 0}, {"type": "integer", "format": "int32", "minimum": 0}], "description": "Coupure du déjeuner, en minutes depuis minuit ; ne découpe que les plages qui la\ncontiennent strictement (production)."}, "feries_fermes": {"type": "array", "items": {"type": "string"}, "description": "Fériés où l'on ferme (codes de [`FERIES`]). La production stockait l'inverse (ceux où\nl'on reste ouvert) : piège noté à la reprise, évité ici."}, "fermetures": {"type": "array", "items": {"type": "string"}, "description": "Fermetures exceptionnelles, `AAAA-MM-JJ`."}}}, "GrilleTarifaire": {"type": "object", "description": "Une grille, sans ses lignes.", "required": ["id", "organisation", "nature", "nom", "effet", "par_defaut", "lignes", "bouchon"], "properties": {"id": {"type": "string", "format": "uuid"}, "organisation": {"type": "string", "format": "uuid", "description": "Organisation propriétaire (opérateur ou revendeur)."}, "nature": {"$ref": "#/components/schemas/NatureGrille"}, "nom": {"type": "string"}, "effet": {"type": "string", "format": "date", "description": "Date d'effet (une grille d'achat s'applique aux appels à partir de ce jour)."}, "par_defaut": {"type": "boolean"}, "lignes": {"type": "integer", "format": "int64"}, "bouchon": {"type": "boolean", "description": "La grille a une ligne bouchon `*` (D110). Sans elle, un appel vers une destination absente\nn'est pas valorisé : à signaler pour une grille de vente."}, "forfait": {"oneOf": [{"$ref": "#/components/schemas/Forfait", "description": "Forfait indicatif par défaut d'une grille de vente (D120), pour la marge ; absent :\naucun."}, {"type": "null"}]}}}, "GrilleTarifaireDetaillee": {"allOf": [{"$ref": "#/components/schemas/GrilleTarifaire"}, {"type": "object", "required": ["lignes_detail"], "properties": {"lignes_detail": {"type": "array", "items": {"$ref": "#/components/schemas/LigneTarifaire"}}}}], "description": "Une grille et ses lignes, par préfixe."}, "Groupe": {"type": "object", "required": ["ext", "nom", "strategie", "duree", "membres"], "properties": {"ext": {"type": "string"}, "nom": {"type": "string"}, "strategie": {"$ref": "#/components/schemas/Strategie"}, "duree": {"type": "integer", "format": "int32", "description": "Secondes de sonnerie du groupe.", "minimum": 0}, "membres": {"type": "array", "items": {"$ref": "#/components/schemas/Membre"}}}}, "HeureSimultanee": {"type": "object", "description": "Pic d'appels simultanés d'une heure.", "required": ["debut", "pic"], "properties": {"debut": {"type": "string", "format": "date-time"}, "pic": {"type": "integer", "format": "int64"}}}, "Identifiants": {"type": "object", "required": ["courriel", "mot_de_passe"], "properties": {"courriel": {"type": "string"}, "mot_de_passe": {"type": "string"}, "confiance": {"type": "boolean", "description": "Rester connecté sur ce navigateur pendant 30 jours (appareil de confiance, D53, D76).\nPris en compte ici pour un compte sans second facteur ; sinon, le choix se fait à l'étape\ndu code (`confiance` de `/connexion/second-facteur`)."}}}, "IdentifiantsAppareil": {"type": "object", "description": "Identifiants HTTP de l'appareil, pour le configurer à la main.", "required": ["adresse", "identifiant", "mot_de_passe"], "properties": {"adresse": {"type": "string"}, "identifiant": {"type": "string"}, "mot_de_passe": {"type": "string"}}}, "InformationsSip": {"type": "object", "description": "Ce qu'il faut pour configurer un téléphone ou un logiciel SIP à la main, sans le mot de passe\n(D114 : il se demande à part).", "required": ["identifiant", "domaine", "acces"], "properties": {"identifiant": {"type": "string", "description": "Identifiant SIP et d'authentification : le numéro du poste."}, "domaine": {"type": "string", "description": "Serveur (registrar) et domaine SIP du client, qui est aussi le realm d'authentification : sous\nle suffixe de l'instance, il pointe vers elle par l'enregistrement DNS générique (D108)."}, "proxy_sortant": {"type": ["string", "null"], "description": "Proxy sortant, seulement quand le domaine n'est pas sous le suffixe de l'instance (domaine\nrepris tel quel, instance sans suffixe) et peut donc ne pas pointer vers elle : le téléphone\ngarde le domaine et joint ce proxy."}, "acces": {"type": "array", "items": {"$ref": "#/components/schemas/AccesSip"}, "description": "Ports et transports ouverts, du plus courant au chiffré (D89)."}}}, "InscriptionMobile": {"type": "object", "description": "Inscription de l'application mobile, ou rafraîchissement de son jeton push.", "required": ["plateforme", "jeton", "identifiant"], "properties": {"plateforme": {"type": "string", "description": "`ios` (APNs, PushKit VoIP) ou `android` (FCM)."}, "jeton": {"type": "string", "description": "Jeton push de l'appareil ; l'application le met aussi en paramètre `pn-prid` du\n`Contact` de son `REGISTER` (RFC 8599), pour être reconnue à son inscription."}, "identifiant": {"type": "string", "description": "Identifiant stable de l'installation."}, "version_appli": {"type": "string"}}}, "InscriptionTotp": {"type": "object", "description": "Secret à saisir dans l'application d'authentification, affiché une seule fois.", "required": ["secret", "uri"], "properties": {"secret": {"type": "string", "description": "Secret en base32."}, "uri": {"type": "string", "description": "URI `otpauth://`, à afficher en QR code."}}}, "Installation": {"allOf": [{"$ref": "#/components/schemas/LiensPoste"}, {"type": "object", "required": ["poste", "marque"], "properties": {"poste": {"type": "string"}, "nom": {"type": ["string", "null"], "description": "Nom présenté du poste, s'il en a un."}, "marque": {"type": "string", "description": "Nom de l'opérateur."}}}], "description": "Ce que la page d'installation affiche."}, "InstallationEnvoyee": {"type": "object", "required": ["courriel"], "properties": {"courriel": {"type": "string", "description": "Adresse à laquelle le lien est parti."}}}, "InstallationMobile": {"type": "object", "description": "Lien d'installation de l'application mobile maison, à montrer en QR code.", "required": ["lien", "expire"], "properties": {"lien": {"type": "string", "description": "Adresse que l'application échange contre un jeton d'appareil (`POST`), une seule fois."}, "expire": {"type": "string", "format": "date-time", "description": "Fin de validité (RFC 3339)."}}}, "InstanceAccueil": {"type": "object", "description": "Une instance de module sur l'accueil.", "required": ["id", "module"], "properties": {"id": {"type": "string", "description": "Identifiant de l'instance, unique dans la disposition (minuscules, chiffres et tirets)."}, "module": {"type": "string", "description": "Module du catalogue du portail (minuscules, chiffres et tirets)."}, "taille": {"oneOf": [{"$ref": "#/components/schemas/TailleModule", "description": "Taille ; absente : celle par défaut du module."}, {"type": "null"}]}, "periode": {"oneOf": [{"$ref": "#/components/schemas/PeriodeModule", "description": "Période ; absente : celle par défaut du module."}, {"type": "null"}]}, "comparer": {"type": "boolean", "description": "Comparer à la période précédente, là où le module le permet."}}}, "InvitationEnvoyee": {"type": "object", "required": ["courriel"], "properties": {"courriel": {"type": "string", "description": "Adresse à laquelle l'invitation est partie."}}}, "IpBannie": {"type": "object", "required": ["ip", "debut", "fin", "raison", "echecs"], "properties": {"ip": {"type": "string"}, "debut": {"type": "string", "description": "RFC 3339."}, "fin": {"type": "string", "description": "Fin prévue (RFC 3339)."}, "raison": {"type": "string", "description": "`authentification`, `domaine_ip` ou `manuel`."}, "echecs": {"type": "integer", "format": "int32"}, "compte": {"type": ["string", "null"], "description": "Compte visé par le dernier échec (`poste@domaine`, ou le domaine seul) : le téléphone\nmal configuré à retrouver."}, "agent": {"type": ["string", "null"], "description": "`User-Agent` de l'appareil au dernier échec."}}}, "JetonInstallation": {"type": "object", "required": ["jeton"], "properties": {"jeton": {"type": "string", "description": "Jeton du lien d'installation reçu par e-mail."}}}, "JetonMiseEnRoute": {"type": "object", "required": ["jeton"], "properties": {"jeton": {"type": "string", "description": "Jeton de l'adresse de mise en route (après le `#`)."}}}, "JetonSupervision": {"type": "object", "required": ["actif"], "properties": {"actif": {"type": "boolean", "description": "Un jeton est en place : `/metrics` répond à qui le présente."}, "prefixe": {"type": ["string", "null"], "description": "Début du jeton (`cxs_1a2b3c`), pour le reconnaître."}, "cree_le": {"type": ["string", "null"], "format": "date-time"}, "derniere_utilisation": {"type": ["string", "null"], "format": "date-time", "description": "Dernière lecture de `/metrics` avec ce jeton (à la minute près)."}}}, "JetonSupervisionCree": {"allOf": [{"$ref": "#/components/schemas/JetonSupervision"}, {"type": "object", "required": ["secret"], "properties": {"secret": {"type": "string", "description": "À mettre dans la configuration de Prometheus (`authorization: credentials`)."}}}], "description": "Jeton créé : `secret` n'est donné qu'ici, une seule fois."}, "JourClient": {"type": "object", "description": "Appels reçus un jour, par issue (D66).", "required": ["jour", "recus", "repondus", "messages", "manques"], "properties": {"jour": {"type": "string", "format": "date"}, "recus": {"type": "integer", "format": "int64"}, "repondus": {"type": "integer", "format": "int64", "description": "Mis en relation avec une personne."}, "messages": {"type": "integer", "format": "int64", "description": "L'appelant a laissé un message."}, "manques": {"type": "integer", "format": "int64", "description": "Ni mis en relation, ni message."}}}, "JourParc": {"type": "object", "description": "Appels d'un jour du parc.", "required": ["jour", "entrants", "sortants", "internes"], "properties": {"jour": {"type": "string", "format": "date"}, "entrants": {"type": "integer", "format": "int64"}, "sortants": {"type": "integer", "format": "int64", "description": "Sortants, mises en relation comprises (D104)."}, "internes": {"type": "integer", "format": "int64"}}}, "Journal": {"type": "object", "description": "Une page du journal.", "required": ["appels", "numeros_masques"], "properties": {"appels": {"type": "array", "items": {"$ref": "#/components/schemas/Appel"}}, "numeros_masques": {"type": "boolean", "description": "Les numéros externes sont masqués (`06••••••78`) ; jamais pour le titulaire qui demande\nles appels de son propre poste."}, "suivant": {"type": ["string", "null"], "format": "date-time", "description": "À passer en `avant` pour la page suivante ; absent : dernière page."}}}, "LangueDuCompte": {"type": "object", "properties": {"langue": {"type": ["string", "null"], "description": "`fr`, `en`, ou absente : celle de l'organisation."}}}, "LangueOrganisation": {"type": "object", "required": ["langue"], "properties": {"langue": {"type": "string", "description": "`fr` ou `en`."}}}, "Licence": {"type": "object", "required": ["instance", "cle_publique", "hub", "utilisateurs", "clients", "releves", "licence"], "properties": {"instance": {"type": "string", "format": "uuid", "description": "Identifiant de l'instance, à donner à l'éditeur avec la clé publique."}, "cle_publique": {"type": "string", "description": "Clé publique Ed25519 de l'instance (hexadécimal) : le Hub vérifie les relevés avec elle."}, "hub": {"type": "boolean", "description": "Relevés envoyés au Hub ; sinon, relevé manuel (téléchargement)."}, "utilisateurs": {"type": "integer", "format": "int64", "description": "Utilisateurs en ce moment : comptes actifs des clients (D71)."}, "clients": {"type": "array", "items": {"$ref": "#/components/schemas/UtilisateursClient"}, "description": "Détail par client (son nom ne quitte pas l'instance)."}, "releves": {"type": "array", "items": {"$ref": "#/components/schemas/ReleveLicence"}, "description": "Derniers relevés, du plus récent au plus ancien."}, "licence": {"$ref": "#/components/schemas/EtatLicence", "description": "Licence de l'éditeur (D78)."}}}, "Lien": {"type": "object", "description": "Un lien : la sortie `sortie` du module `de` envoie l'appel vers `vers` (module ou adresse).", "required": ["de", "sortie", "vers"], "properties": {"de": {"type": "string"}, "sortie": {"type": "string"}, "vers": {"type": "string"}}}, "LiensPoste": {"type": "object", "description": "Liens d'installation d'un poste.", "required": ["expire"], "properties": {"lien_csc": {"type": ["string", "null"], "description": "Lien CSC de l'application mobile de l'opérateur (Cloud Softphone) ; absent sans Cloud ID\nréglé, ou hors reprise Acrobits (D119)."}, "url_acrobits": {"type": ["string", "null"], "description": "Lien https d'Acrobits Softphone, à ouvrir sur le téléphone (il rouvre l'application) ;\nabsent hors reprise Acrobits (D119)."}, "expire": {"type": "string", "description": "Fin de validité des liens (RFC 3339) ; la configuration installée se renouvelle d'elle-même."}}}, "LigneAppareil": {"type": "object", "description": "Un compte d'un appareil.", "required": ["rang"], "properties": {"rang": {"type": "integer", "format": "int32", "minimum": 0}, "poste": {"type": ["string", "null"]}, "nom_poste": {"type": ["string", "null"]}, "combine": {"type": ["integer", "null"], "format": "int32", "description": "Combiné d'une base DECT.", "minimum": 0}}}, "LigneCapturee": {"type": "object", "description": "Une ligne capturée, envoyée en événement `ligne` (JSON). L'événement `fin` clôt la capture.", "required": ["nature", "niveau", "texte"], "properties": {"nature": {"type": "string", "description": "`sip` (trace SIP) ou `journal`."}, "niveau": {"type": "integer", "format": "int32", "description": "Niveau syslog (0 urgence … 7 débogage).", "minimum": 0}, "texte": {"type": "string"}, "sip": {"oneOf": [{"$ref": "#/components/schemas/MessageSip", "description": "Message SIP découpé (lignes `sip` lisibles seulement)."}, {"type": "null"}]}}}, "LigneDifferenceProfil": {"type": "object", "description": "Une ligne de différence.", "required": ["nature", "texte"], "properties": {"nature": {"type": "string", "description": "`egale`, `retiree` (seulement dans la copie) ou `ajoutee` (seulement dans la version\nlivrée)."}, "texte": {"type": "string"}}}, "LigneTarifaire": {"type": "object", "description": "Une ligne de grille. Montants en millionièmes de la devise de l'instance, HT.", "required": ["prefixe", "destination", "prix_minute", "frais", "palier"], "properties": {"prefixe": {"type": "string", "description": "Préfixe E.164 (`+336`), ou `*` : le bouchon, toute destination absente (D110)."}, "destination": {"type": "string"}, "prix_minute": {"type": "integer", "format": "int64"}, "frais": {"type": "integer", "format": "int64"}, "palier": {"type": "string", "description": "`minimum/incrément` en secondes (`60/30`)."}}}, "LimitationPlafond": {"type": "object", "description": "Limitation en cours d'un client.", "required": ["niveau", "depuis", "levable"], "properties": {"niveau": {"type": "string", "description": "`heure` ou `jour` : le seuil atteint."}, "depuis": {"type": "string", "format": "date-time"}, "levable": {"type": "boolean", "description": "Le compte connecté peut-il la lever ?"}}}, "Machine": {"type": "object", "description": "Relevés de la machine et dernière sauvegarde.", "required": ["releves"], "properties": {"hote": {"type": ["string", "null"], "description": "Machine des relevés : celle du relevé le plus récent (après une bascule, D74, la\nnouvelle active)."}, "releves": {"type": "array", "items": {"$ref": "#/components/schemas/ReleveMachine"}, "description": "Relevés de cette machine, du plus ancien au plus récent, un par minute."}, "derniere_sauvegarde": {"oneOf": [{"$ref": "#/components/schemas/SauvegardeFaite"}, {"type": "null"}]}}}, "Marque": {"type": "object", "required": ["nom", "couleur", "couleur_foncee", "icone", "icone_deposee", "couleur_menu", "couleur_menu_texte", "couleur_menu_texte_fort", "couleur_menu_active", "couleur_texte", "couleur_texte_discret"], "properties": {"nom": {"type": "string", "description": "Nom affiché : celui réglé, sinon celui de l'opérateur."}, "couleur": {"type": "string", "description": "Couleur d'accent (`#rrggbb`)."}, "couleur_foncee": {"type": "string", "description": "Accent assombri (survol, liens visités)."}, "logo": {"type": ["string", "null"], "description": "Adresse du logo (change avec lui), s'il y en a un."}, "icone": {"type": "string", "description": "Adresse de l'icône (favicon, application installée ; change avec la marque) : celle\ndéposée, sinon l'initiale du nom sur l'accent."}, "icone_deposee": {"type": "boolean", "description": "Une icône a été déposée (PNG), sinon l'icône est générée."}, "couleur_menu": {"type": "string", "description": "Fond du menu latéral (`#rrggbb`)."}, "couleur_menu_texte": {"type": "string", "description": "Texte du menu, déduit du fond (contraste de 4,5 au moins)."}, "couleur_menu_texte_fort": {"type": "string", "description": "Texte fort du menu (nom, entrée active), déduit du fond."}, "couleur_menu_active": {"type": "string", "description": "Fond de l'entrée active du menu, déduit du fond."}, "couleur_texte": {"type": "string", "description": "Couleur des textes (contraste de 7 au moins sur le fond des pages)."}, "couleur_texte_discret": {"type": "string", "description": "Textes discrets (aides, libellés), déduits des textes."}}}, "Membre": {"type": "object", "required": ["cible", "delai"], "properties": {"cible": {"type": "string", "description": "`poste:100` ou `externe:0612345678` (international : `externe:0041…`)."}, "delai": {"type": "integer", "format": "int32", "description": "Secondes avant de faire sonner ce membre.", "minimum": 0}, "duree": {"type": ["integer", "null"], "format": "int32", "description": "Secondes de sonnerie de ce membre ; `None` : la durée du groupe.", "minimum": 0}}}, "MessageExporte": {"type": "object", "required": ["date", "numero_appelant", "duree"], "properties": {"date": {"type": "integer", "format": "int64", "description": "Dépôt (secondes Unix)."}, "numero_appelant": {"type": "string"}, "duree": {"type": "integer", "format": "int64"}, "transcription": {"type": ["string", "null"], "description": "Transcription, pour la personne elle-même et l'admin de son entreprise (D57)."}}}, "MessagePcap": {"type": "object", "description": "Message d'un pcap : les messages SIP d'une capture conviennent tels quels.", "required": ["transport", "source", "destination", "horodatage", "message"], "properties": {"transport": {"type": "string", "description": "`udp`, `tcp`, `tls`, `ws` ou `wss` (TLS et websocket sont écrits en TCP, en clair)."}, "source": {"type": "string", "description": "Émetteur, `ip:port`."}, "destination": {"type": "string", "description": "Destinataire, `ip:port`."}, "horodatage": {"type": "string", "format": "date-time"}, "message": {"type": "string", "description": "Message SIP tel que sur le réseau."}}}, "MessageSip": {"type": "object", "description": "Message SIP de la trace, vu du moteur de téléphonie.", "required": ["sens", "transport", "source", "destination", "horodatage", "resume", "message"], "properties": {"sens": {"type": "string", "description": "`recu` ou `envoye` par le moteur de téléphonie."}, "transport": {"type": "string", "description": "`udp`, `tcp`, `tls`, `ws` ou `wss`."}, "source": {"type": "string", "description": "Émetteur, `ip:port`."}, "destination": {"type": "string", "description": "Destinataire, `ip:port`."}, "horodatage": {"type": "string", "format": "date-time", "description": "Instant du message."}, "resume": {"type": "string", "description": "Ligne de requête ou d'état (`INVITE sip:… SIP/2.0`, `SIP/2.0 180 Ringing`)."}, "methode": {"type": ["string", "null"], "description": "Méthode (celle du `CSeq` pour une réponse)."}, "statut": {"type": ["integer", "null"], "format": "int32", "description": "Code d'une réponse.", "minimum": 0}, "call_id": {"type": ["string", "null"], "description": "Dialogue (`Call-ID`)."}, "message": {"type": "string", "description": "Message tel que sur le réseau (CRLF), corps compris."}}}, "MessageVocal": {"type": "object", "description": "Un message vocal.", "required": ["id", "depose_le", "duree", "lu", "appelant_nom", "appelant_numero"], "properties": {"id": {"type": "string", "format": "uuid"}, "depose_le": {"type": "string", "format": "date-time"}, "duree": {"type": "integer", "format": "int64", "description": "Durée en secondes."}, "lu": {"type": "boolean"}, "appelant_nom": {"type": "string"}, "appelant_numero": {"type": "string", "description": "Masqué (`06••••••78`) sans la permission `messagerie.ecouter`."}, "transcription": {"type": ["string", "null"], "description": "Absente sans la permission `messagerie.ecouter`, ou pas encore transcrit."}}}, "MiseEnRoute": {"type": "object", "required": ["etapes", "terminees", "terminee", "masquee"], "properties": {"etapes": {"type": "array", "items": {"$ref": "#/components/schemas/EtapeMiseEnRoute"}, "description": "Les neuf étapes, dans l'ordre."}, "terminees": {"type": "integer", "description": "Étapes faites ou passées.", "minimum": 0}, "terminee": {"type": "boolean", "description": "Toutes les étapes sont faites ou passées."}, "masquee": {"type": "boolean", "description": "Tuile de l'accueil masquée."}}}, "ModeForfait": {"type": "string", "description": "Assiette du forfait.", "enum": ["par_utilisateur", "global"]}, "ModeleDisponible": {"type": "object", "description": "Un modèle qu'on peut ajouter à un client.", "required": ["profil", "profil_nom", "etiquette", "code", "nom", "comptes", "touches", "premiere_touche", "combines"], "properties": {"profil": {"type": "string"}, "profil_nom": {"type": "string"}, "etiquette": {"type": "string", "description": "`teste`, `communautaire` ou `copie`."}, "code": {"type": "string"}, "nom": {"type": "string"}, "comptes": {"type": "integer", "format": "int32", "minimum": 0}, "touches": {"type": "integer", "format": "int32", "minimum": 0}, "premiere_touche": {"type": "integer", "format": "int32", "minimum": 0}, "combines": {"type": "boolean"}, "redirection": {"type": ["string", "null"], "description": "Service de redirection de la marque (`yealink-rps`)."}}}, "ModeleMateriel": {"type": "object", "description": "Un modèle couvert par un profil.", "required": ["code", "nom", "comptes", "touches"], "properties": {"code": {"type": "string", "description": "Code court, stable (`t54w`)."}, "nom": {"type": "string"}, "comptes": {"type": "integer", "format": "int32", "description": "Comptes SIP que le modèle porte (lignes, ou combinés d'une base DECT).", "minimum": 0}, "touches": {"type": "integer", "format": "int32", "description": "Touches programmables ; 0 si le modèle n'en a pas.", "minimum": 0}}}, "ModificationAppareil": {"type": "object", "description": "Modification d'un appareil : seuls les champs donnés changent.", "properties": {"nom": {"type": ["string", "null"]}, "numero_de_serie": {"type": ["string", "null"], "description": "Chaîne vide : retiré."}, "modele": {"type": ["string", "null"]}, "touches": {"type": ["array", "null"], "items": {"$ref": "#/components/schemas/ToucheAppareil"}}, "parametres": {"type": ["string", "null"], "description": "Paramètres supplémentaires (opérateur et revendeur seulement)."}}}, "ModificationClient": {"type": "object", "properties": {"nom": {"type": ["string", "null"], "description": "Nom du client (raison sociale)."}, "actif": {"type": ["boolean", "null"], "description": "`false` : client suspendu ; `true` : réactivé."}, "enregistrement_autorise": {"type": ["boolean", "null"], "description": "Enregistrement des appels autorisé (D111). Coupé : les postes qui enregistraient sont\nsuspendus, ni réglage ni écoute dans l'espace du client ; rétabli à la réactivation. Les\nenregistrements existants sont gardés (rétention normale)."}, "ajout_utilisateurs_autorise": {"type": ["boolean", "null"], "description": "L'admin du client peut ajouter des utilisateurs et des postes (D121). Coupé (par\ndéfaut) : seuls l'opérateur et le revendeur en ajoutent ; les comptes existants restent."}}}, "ModificationCompte": {"type": "object", "properties": {"nom": {"type": ["string", "null"]}, "courriel": {"type": ["string", "null"]}, "role": {"type": ["string", "null"], "description": "Rôle du même niveau : `admin_client` ou `utilisateur` chez un client, `admin_operateur`\nou `support_operateur` chez l'opérateur."}, "actif": {"type": ["boolean", "null"], "description": "`false` : compte désactivé (plus de connexion, ne compte plus pour la licence) et son\nposte hors service ; `true` : réactivé."}, "telephone_seulement": {"type": ["boolean", "null"], "description": "Compte « téléphone seulement » (D107) : sa session n'ouvre que le softphone, et ses\napplications autorisées (OAuth) sont révoquées. Rôle `utilisateur` seulement ; passé\n`admin_client`, le compte ne l'est plus."}}}, "ModificationProfil": {"type": "object", "description": "Nouvelle version d'une copie.", "required": ["nom", "contenu"], "properties": {"nom": {"type": "string"}, "contenu": {"$ref": "#/components/schemas/ContenuProfil"}, "resume": {"type": "string", "description": "Ce qui change, pour l'historique."}}}, "Module": {"oneOf": [{"type": "object", "description": "Un numéro du client (E.164), point d'entrée des appels.", "required": ["numero", "type"], "properties": {"numero": {"type": "string"}, "type": {"type": "string", "enum": ["numero"]}}}, {"allOf": [{"$ref": "#/components/schemas/Grille", "description": "Horaires : sorties `ouvert` et `ferme`."}, {"type": "object", "required": ["type"], "properties": {"type": {"type": "string", "enum": ["grille"]}}}], "description": "Horaires : sorties `ouvert` et `ferme`."}, {"allOf": [{"$ref": "#/components/schemas/Svi", "description": "Serveur vocal : touches `0` à `9`, `*` et `#` (D50), sortie `sinon` (rien tapé ou trop\nd'erreurs)."}, {"type": "object", "required": ["type"], "properties": {"type": {"type": "string", "enum": ["svi"]}}}], "description": "Serveur vocal : touches `0` à `9`, `*` et `#` (D50), sortie `sinon` (rien tapé ou trop\nd'erreurs)."}, {"allOf": [{"$ref": "#/components/schemas/Groupe", "description": "Groupe d'appel : sortie `nonrepondu`."}, {"type": "object", "required": ["type"], "properties": {"type": {"type": "string", "enum": ["groupe"]}}}], "description": "Groupe d'appel : sortie `nonrepondu`."}, {"allOf": [{"$ref": "#/components/schemas/Attente", "description": "File d'attente à un agent : sans réponse, la messagerie de l'agent (fixe)."}, {"type": "object", "required": ["type"], "properties": {"type": {"type": "string", "enum": ["attente"]}}}], "description": "File d'attente à un agent : sans réponse, la messagerie de l'agent (fixe)."}, {"allOf": [{"$ref": "#/components/schemas/Conference", "description": "Salle de conférence."}, {"type": "object", "required": ["type"], "properties": {"type": {"type": "string", "enum": ["conference"]}}}], "description": "Salle de conférence."}, {"allOf": [{"$ref": "#/components/schemas/Renvoi", "description": "Renvoi vers un numéro externe (production du 12/10/2026) : une fin de parcours, sans\nsortie. Numéros, touches, horaires et groupes y mènent ; changer le numéro une fois met\ntout à jour."}, {"type": "object", "required": ["type"], "properties": {"type": {"type": "string", "enum": ["renvoi"]}}}], "description": "Renvoi vers un numéro externe (production du 12/10/2026) : une fin de parcours, sans\nsortie. Numéros, touches, horaires et groupes y mènent ; changer le numéro une fois met\ntout à jour."}, {"allOf": [{"$ref": "#/components/schemas/Sip", "description": "Connecteur SIP (production du 13/10/2026) : une fin de parcours qui passe l'appel à un\nservice tiers (assistant téléphonique…) par sa propre passerelle, un trunk SIP avec\nenregistrement, sans minute sortante. Le mot de passe n'est pas dans le parcours (rendu\npar la simulation, gardé par les versions) : il est chiffré à part (D27)."}, {"type": "object", "required": ["type"], "properties": {"type": {"type": "string", "enum": ["sip"]}}}], "description": "Connecteur SIP (production du 13/10/2026) : une fin de parcours qui passe l'appel à un\nservice tiers (assistant téléphonique…) par sa propre passerelle, un trunk SIP avec\nenregistrement, sans minute sortante. Le mot de passe n'est pas dans le parcours (rendu\npar la simulation, gardé par les versions) : il est chiffré à part (D27)."}]}, "Moi": {"type": "object", "description": "Compte connecté.", "required": ["id", "courriel", "nom", "role", "organisation_id"], "properties": {"id": {"type": "string", "format": "uuid"}, "courriel": {"type": "string"}, "nom": {"type": "string"}, "role": {"type": "string", "description": "Rôle prédéfini (`admin_operateur`, `admin_client`…)."}, "organisation_id": {"type": "string", "format": "uuid"}, "organisation": {"oneOf": [{"$ref": "#/components/schemas/OrganisationDuCompte", "description": "Organisation du compte (absente dans les réponses de connexion)."}, {"type": "null"}]}, "poste": {"type": ["string", "null"], "description": "Numéro du poste du compte, s'il en a un (absent dans les réponses de connexion)."}, "langue": {"type": ["string", "null"], "description": "Langue du portail pour ce compte (`fr` ou `en`) : la sienne, sinon celle de son\norganisation (absente dans les réponses de connexion)."}, "langue_compte": {"type": ["string", "null"], "description": "Langue choisie par le compte lui-même ; absente : celle de l'organisation."}, "alerte_licence": {"oneOf": [{"$ref": "#/components/schemas/EtatLicence", "description": "Licence de l'éditeur échue, ou qui finit dans 14 jours au plus (D78), pour le bandeau :\ncomptes de l'opérateur et des revendeurs seulement."}, {"type": "null"}]}, "lecture_seule": {"type": ["string", "null"], "format": "date", "description": "Instance en lecture seule depuis ce jour (`AAAA-MM-JJ`, licence échue depuis plus de\n30 jours, D78) : le portail désactive les écritures, sauf celles qui restent permises\n(connexion, usage téléphonique, chargement de la licence…). Absent sinon ; pour tout\ncompte."}, "fonctions": {"oneOf": [{"$ref": "#/components/schemas/Fonctions", "description": "Fonctions activées par l'opérateur (D94), pour les menus du portail (absentes dans les\nréponses de connexion)."}, {"type": "null"}]}, "telephone_seulement": {"type": ["boolean", "null"], "description": "Compte « téléphone seulement » (D107) : le portail le mène au softphone (`/telephone/`)\n(absent dans les réponses de connexion)."}, "reprise_acrobits": {"type": ["boolean", "null"], "description": "Reprise Acrobits active sur l'instance (D119) : le portail montre alors ses réglages et\nses liens. Absent sinon."}, "devise": {"type": ["string", "null"], "description": "Devise de l'instance (D124, lot 3, code ISO 4217, `EUR` par défaut) : tous les montants\nsont en millionièmes de cette devise (absente dans les réponses de connexion)."}}}, "MonTelephone": {"type": "object", "description": "Ce qu'il faut au softphone pour s'enregistrer et appeler.", "required": ["poste", "domaine", "mot_de_passe", "nom_affiche", "websocket", "serveurs_ice", "repertoire_partageable", "pays", "langue"], "properties": {"poste": {"type": "string", "description": "Numéro du poste, identifiant SIP."}, "domaine": {"type": "string", "description": "Domaine SIP du client."}, "mot_de_passe": {"type": "string", "description": "Mot de passe SIP du poste."}, "nom_affiche": {"type": "string", "description": "Nom présenté aux appels internes."}, "numero_externe": {"type": ["string", "null"], "description": "Numéro externe présenté par le poste (E.164) : le numéro présenté réglé pour le poste,\nsinon le numéro principal du client (NDI de son trunk) ; absent s'il n'y en a pas."}, "websocket": {"type": "string", "description": "Adresse du relais SIP sur WebSocket (`wss://…/api/v1/telephone/ws`)."}, "serveurs_ice": {"type": "array", "items": {"$ref": "#/components/schemas/ServeurIce"}, "description": "Serveurs STUN et TURN (identifiants TURN valables 12 heures) ; vide sans TURN réglé."}, "repertoire_partageable": {"type": "boolean", "description": "Le compte peut ajouter au répertoire commun du client : son admin, ou un collaborateur\nsi le client l'ouvre à ses collaborateurs."}, "pays": {"type": "string", "description": "Pays du client (D124, code de `GET /pays`) : le softphone lit les numéros saisis dans son\nplan de numérotation."}, "langue": {"type": "string", "description": "Langue du compte (`fr` ou `en`) : la sienne, sinon celle de son organisation (D124,\nlot 3). Les applications mobile et de bureau y passent leurs textes."}}}, "MotDePasseConnecteur": {"type": "object", "description": "Mot de passe d'un connecteur SIP : jamais relu, jamais dans le parcours.", "required": ["mot_de_passe"], "properties": {"mot_de_passe": {"type": "string"}}}, "MotDePasseSip": {"type": "object", "description": "Mot de passe SIP d'un poste, révélé à la demande (D114).", "required": ["mot_de_passe"], "properties": {"mot_de_passe": {"type": "string"}}}, "MoteurSynthese": {"type": "string", "description": "Moteur de la voix de synthèse (D123).", "enum": ["piper", "google"]}, "Nature": {"type": "string", "description": "Nature d'une annonce.", "enum": ["accueil_svi", "fermeture", "predecroche_numero", "predecroche_groupe", "musique_file"]}, "NatureGrille": {"type": "string", "enum": ["achat", "vente_revendeur", "vente_client"]}, "NePasDeranger": {"type": "object", "description": "« Ne pas déranger » d'un poste : le téléphone ne sonne plus, l'appel suit le renvoi sur\noccupation, sinon la messagerie (D107, écran Statut du softphone).", "required": ["actif"], "properties": {"actif": {"type": "boolean"}}}, "NiveauForfait": {"type": "object", "description": "Forfait d'un client à un niveau de vente.", "properties": {"propre": {"oneOf": [{"$ref": "#/components/schemas/Forfait", "description": "Forfait propre au client ; absent : celui de la grille."}, {"type": "null"}]}, "grille": {"oneOf": [{"$ref": "#/components/schemas/Forfait", "description": "Forfait par défaut de la grille de vente du client à ce niveau (attribuée, sinon par\ndéfaut) ; absent : aucun."}, {"type": "null"}]}, "applique": {"oneOf": [{"$ref": "#/components/schemas/Forfait", "description": "Forfait appliqué : le propre, sinon celui de la grille ; absent : aucun forfait."}, {"type": "null"}]}, "mensuel": {"type": ["integer", "null"], "format": "int64", "description": "Montant d'un mois entier pour le nombre d'utilisateurs actuel ; absent : aucun forfait."}}}, "NouveauBannissement": {"type": "object", "required": ["ip"], "properties": {"ip": {"type": "string", "description": "Adresse IPv4 ou IPv6."}, "duree_secondes": {"type": ["integer", "null"], "format": "int32", "description": "Durée en secondes (60 à 2 592 000) ; absente : celle des réglages."}}}, "NouveauBrouillon": {"type": "object", "required": ["contenu"], "properties": {"contenu": {"$ref": "#/components/schemas/Parcours"}, "version_base": {"type": ["integer", "null"], "format": "int32", "description": "Version publiée dont part le brouillon ; aucune : absent ou `null`."}}}, "NouveauClient": {"type": "object", "required": ["nom", "domaine"], "properties": {"nom": {"type": "string", "description": "Nom du client (raison sociale)."}, "domaine": {"type": "string", "description": "Identifiant du client (`client`), complété par le suffixe des domaines de l'instance\n(D108), ou domaine SIP complet (`client.exemple`) ; c'est aussi son contexte dans le moteur\nde téléphonie."}}}, "NouveauCompte": {"type": "object", "required": ["courriel", "nom", "role"], "properties": {"courriel": {"type": "string"}, "nom": {"type": "string"}, "role": {"type": "string", "description": "`admin_operateur` ou `support_operateur` chez l'opérateur, `admin_revendeur` chez un\nrevendeur."}}}, "NouveauMotDePasse": {"type": "object", "required": ["jeton", "mot_de_passe"], "properties": {"jeton": {"type": "string", "description": "Jeton d'invitation ou de réinitialisation reçu par lien."}, "mot_de_passe": {"type": "string"}}}, "NouveauNumero": {"type": "object", "required": ["numero"], "properties": {"numero": {"type": "string", "description": "E.164 (`+33123456789`)."}, "pays": {"type": ["string", "null"], "description": "Pays (ISO 3166-1 alpha-2) ; par défaut, celui de l'indicatif s'il est pris en charge\n(`FR` pour un `+33`, `BE`, `CH`, `GB`, `US` ou `CA` selon l'indicatif régional). Il doit\ncorrespondre à l'indicatif (D124)."}, "fournisseur": {"type": ["string", "null"]}}}, "NouveauPosteDuCompte": {"type": "object", "required": ["numero"], "properties": {"numero": {"type": "string", "description": "Numéro interne à créer (2 à 8 chiffres), libre chez le client."}}}, "NouveauProfilTrunk": {"type": "object", "required": ["nom", "proxy", "format"], "properties": {"nom": {"type": "string"}, "proxy": {"type": "string", "description": "Adresse du C5 : `hôte` ou `hôte:port`."}, "format": {"$ref": "#/components/schemas/Format"}, "reseaux": {"type": "array", "items": {"type": "string"}, "description": "Réseaux du fournisseur (CIDR) d'où viennent ses appels."}}}, "NouveauReglageAssistant": {"type": "object", "required": ["budget_instance_centimes"], "properties": {"cle": {"type": ["string", "null"], "description": "Clé d'API Claude de l'opérateur ; absente : la clé enregistrée est gardée."}, "modele": {"type": ["string", "null"], "description": "Absent : Sonnet."}, "budget_instance_centimes": {"type": "integer", "format": "int64"}, "budget_client_centimes": {"type": ["integer", "null"], "format": "int64"}, "prix_entree_centimes": {"type": ["integer", "null"], "format": "int32", "description": "Absents : tarif de Sonnet (3 et 15 par million de tokens, dans la devise de l'instance)."}, "prix_sortie_centimes": {"type": ["integer", "null"], "format": "int32"}}}, "NouveauReglageOidc": {"type": "object", "required": ["emetteur", "client_id", "libelle"], "properties": {"emetteur": {"type": "string"}, "client_id": {"type": "string"}, "secret": {"type": ["string", "null"], "description": "Secret du client OIDC ; absent : celui déjà enregistré est gardé (obligatoire la\npremière fois)."}, "libelle": {"type": "string"}, "domaines": {"type": "array", "items": {"type": "string"}}, "creation_auto": {"type": "boolean"}}}, "NouveauReglageRps": {"type": "object", "description": "Clés RPS à enregistrer.", "required": ["cle_id", "region", "serveur"], "properties": {"cle_id": {"type": "string"}, "secret": {"type": ["string", "null"], "description": "`AccessKey Secret` ; absent : celui enregistré est gardé."}, "region": {"type": "string"}, "serveur": {"type": "string"}}}, "NouveauReglageSmtp": {"type": "object", "required": ["hote", "port", "securite", "expediteur"], "properties": {"hote": {"type": "string"}, "port": {"type": "integer", "format": "int32", "minimum": 0}, "securite": {"type": "string"}, "identifiant": {"type": ["string", "null"]}, "mot_de_passe": {"type": ["string", "null"], "description": "Absent : le mot de passe enregistré est gardé (s'il y a un identifiant)."}, "expediteur": {"type": "string"}, "nom_expediteur": {"type": "string"}}}, "NouveauReglageSynthese": {"type": "object", "required": ["moteur"], "properties": {"moteur": {"$ref": "#/components/schemas/MoteurSynthese"}, "cle": {"type": ["string", "null"], "description": "Clé d'API Google. Absente : la clé enregistrée est gardée ; vide : effacée."}, "voix_fr": {"type": ["string", "null"], "description": "Voix Google des clients réglés en français ; absente ou vide : `fr-FR-Chirp3-HD-Leda`."}, "voix_en": {"type": ["string", "null"], "description": "Voix Google des clients réglés en anglais ; absente ou vide : `en-US-Chirp3-HD-Leda`."}}}, "NouveauReglageTranscription": {"type": "object", "required": ["url", "modele"], "properties": {"url": {"type": "string"}, "cle": {"type": ["string", "null"], "description": "Absente : la clé enregistrée est gardée ; vide : retirée (moteur local ouvert)."}, "modele": {"type": "string"}, "langue": {"type": ["string", "null"], "description": "Langue imposée à tous les messages (ISO 639-1) ; absente ou vide : celle du client de\nchaque boîte (D81)."}}}, "NouveauRevendeur": {"type": "object", "required": ["nom"], "properties": {"nom": {"type": "string", "description": "Nom du revendeur (raison sociale)."}}}, "NouveauTrunk": {"type": "object", "properties": {"profil_id": {"type": ["string", "null"], "format": "uuid", "description": "Profil de trunk de l'opérateur (D95) : il donne le fournisseur, le serveur, le format et\nles réseaux, et `fournisseur`, `proxy`, `format` et `reseaux` sont ignorés ; absent :\ntrunk saisi en entier."}, "fournisseur": {"type": ["string", "null"]}, "proxy": {"type": ["string", "null"], "description": "Adresse du C5 : `hôte` ou `hôte:port` ; obligatoire sans profil."}, "identifiant": {"type": ["string", "null"], "description": "Identifiant d'enregistrement ; absent : trunk par adresse IP."}, "mot_de_passe": {"type": ["string", "null"], "description": "Obligatoire à la création d'un trunk avec identifiant ; absent en modification : le\nmot de passe enregistré est gardé."}, "format": {"oneOf": [{"$ref": "#/components/schemas/Format", "description": "Obligatoire sans profil."}, {"type": "null"}]}, "reseaux": {"type": "array", "items": {"type": "string"}, "description": "Réseaux du fournisseur (CIDR) d'où viennent ses appels : autorisés dans l'ACL."}, "ndi": {"type": ["string", "null"], "description": "NDI (D48) : un numéro du client, E.164, présenté par défaut sur tout appel qui sort sans\nnuméro propre ; absent : aucun."}}}, "NouveauWebhook": {"type": "object", "description": "Nouvel endpoint, ou endpoint modifié (le secret est gardé).", "required": ["url", "evenements"], "properties": {"url": {"type": "string", "description": "`https://…`, port 443 ou 8443, adresse publique."}, "evenements": {"type": "array", "items": {"type": "string"}, "description": "Client : `voicemail.new`, `call.recorded` ; opérateur ou revendeur : `cdr.month`,\n`client.created`, `extension.created`, `trunk.down`, `trunk.up`."}}}, "NouveauxNumeros": {"type": "object", "required": ["numeros"], "properties": {"numeros": {"type": "array", "items": {"$ref": "#/components/schemas/NouveauNumero"}}}}, "NouvelAppareil": {"type": "object", "description": "Ajout d'un téléphone à un client.", "required": ["mac", "profil", "modele", "lignes"], "properties": {"mac": {"type": "string", "description": "Adresse MAC, séparateurs libres (`80:5E:C0:00:00:01`)."}, "profil": {"type": "string", "description": "Profil : identifiant d'un profil livré ou uuid d'une copie."}, "modele": {"type": "string"}, "nom": {"type": "string"}, "numero_de_serie": {"type": ["string", "null"]}, "lignes": {"type": "array", "items": {"$ref": "#/components/schemas/NouvelleLigne"}}, "touches": {"type": "array", "items": {"$ref": "#/components/schemas/ToucheAppareil"}}, "parametres": {"type": ["string", "null"], "description": "Paramètres supplémentaires (opérateur et revendeur seulement)."}, "declarer_rps": {"type": "boolean", "description": "Déclarer l'appareil au RPS Yealink (profil Yealink, numéro de série requis) : il se\nconfigurera seul à son premier démarrage. Un refus de YMCS n'empêche pas l'ajout : l'état\nle montre (`rps_etat`)."}}}, "NouvelUtilisateur": {"type": "object", "required": ["courriel", "nom", "role"], "properties": {"courriel": {"type": "string"}, "nom": {"type": "string"}, "role": {"type": "string", "description": "`admin_client` ou `utilisateur`."}, "poste": {"type": ["string", "null"], "description": "Numéro de poste interne à créer (2 à 8 chiffres), facultatif."}, "telephone_seulement": {"type": ["boolean", "null"], "description": "Compte « téléphone seulement » (D107) : sa session n'ouvre que le softphone. Absent :\noui pour le rôle `utilisateur`, non pour `admin_client` (qui ne peut pas l'être)."}}}, "NouvelleGrilleTarifaire": {"type": "object", "description": "Nouvelle grille : un CSV ou une grille de départ.", "required": ["nature", "nom"], "properties": {"nature": {"$ref": "#/components/schemas/NatureGrille"}, "nom": {"type": "string"}, "effet": {"type": ["string", "null"], "format": "date", "description": "Date d'effet (`2026-01-01`) ; absente : aujourd'hui."}, "par_defaut": {"type": "boolean"}, "csv": {"type": ["string", "null"], "description": "`prefixe;destination;prix_minute;frais;palier`, une ligne par préfixe."}, "depuis": {"oneOf": [{"$ref": "#/components/schemas/DepuisGrille"}, {"type": "null"}]}, "bouchon": {"oneOf": [{"$ref": "#/components/schemas/BouchonGrille", "description": "Grille de vente : prix du bouchon `*` (D110), qui remplace celui du CSV ou de la grille de\ndépart."}, {"type": "null"}]}, "forfait": {"oneOf": [{"$ref": "#/components/schemas/Forfait", "description": "Grille de vente : forfait indicatif par défaut de ses clients (D120) ; absent : aucun."}, {"type": "null"}]}}}, "NouvelleLigne": {"type": "object", "description": "Un compte à poser sur un appareil.", "required": ["rang", "poste"], "properties": {"rang": {"type": "integer", "format": "int32", "minimum": 0}, "poste": {"type": "string", "description": "Numéro du poste du client."}, "combine": {"type": ["integer", "null"], "format": "int32", "description": "Combiné d'une base DECT ; le rang par défaut.", "minimum": 0}}}, "NouvelleVoixClient": {"type": "object", "properties": {"voix": {"type": ["string", "null"], "description": "Identifiant d'une voix de `…/voix/disponibles` ; absent ou vide : la voix de l'instance."}}}, "NouvellesRestrictions": {"type": "object", "required": ["natures"], "properties": {"natures": {"type": "array", "items": {"type": "string"}, "description": "`surtaxes`, `international`, `sortants` ; vide : aucune."}}}, "Numero": {"type": "object", "required": ["id", "e164", "pays", "fournisseur", "etat"], "properties": {"id": {"type": "string", "format": "uuid"}, "e164": {"type": "string", "description": "Le numéro, en E.164."}, "pays": {"type": "string", "description": "Pays, ISO 3166-1 alpha-2."}, "fournisseur": {"type": "string"}, "etat": {"type": "string", "description": "`libre`, `affecte` (chez un client), `porte_sortant` (a quitté l'opérateur) ou\n`resilie`."}, "revendeur_id": {"type": ["string", "null"], "format": "uuid", "description": "Revendeur pour qui le numéro est réservé."}, "client_id": {"type": ["string", "null"], "format": "uuid", "description": "Client qui a le numéro."}, "poste": {"type": ["string", "null"], "description": "Destination dans le parcours publié, quand c'est directement un poste du client."}, "destination": {"type": ["string", "null"], "description": "Destination dans le parcours publié (`poste:100`, `svi:900`, `grille:800`…) ; aucune :\n`null`."}}}, "NumeroBloque": {"type": "object", "description": "Un numéro bloqué.", "required": ["numero"], "properties": {"numero": {"type": "string", "description": "E.164 en réponse ; national (pays du client), préfixe international ou `+` en saisie."}, "nom": {"type": "string", "description": "Pour s'en souvenir (« démarcheur assurance »), 100 caractères au plus."}}}, "NumeroPresente": {"type": "object", "required": ["poste"], "properties": {"poste": {"type": "string"}, "numero_presente": {"type": ["string", "null"], "description": "E.164."}}}, "OrganisationDuCompte": {"type": "object", "description": "Organisation d'un compte, pour l'en-tête du portail.", "required": ["nom", "type", "fuseau", "pays"], "properties": {"nom": {"type": "string"}, "type": {"type": "string", "description": "`operateur`, `revendeur` ou `client` ; un autre type désigne la racine de l'éditeur."}, "fuseau": {"type": "string", "description": "Fuseau horaire de l'organisation (nom IANA, D81) : le portail y affiche les dates."}, "pays": {"type": "string", "description": "Pays de l'organisation (D124, code de `GET /pays`) : plan de numérotation des numéros\nsaisis par ses comptes."}, "enregistrement_autorise": {"type": ["boolean", "null"], "description": "Client seulement : enregistrement des appels autorisé (D111) ; coupé, le portail masque\nle menu et les réglages d'enregistrement."}, "ajout_utilisateurs_autorise": {"type": ["boolean", "null"], "description": "Client seulement : son admin peut ajouter des utilisateurs et des postes (D121) ; coupé,\nle portail remplace les boutons d'ajout par un renvoi vers l'opérateur."}}}, "OrganisationLue": {"type": "object", "required": ["id", "nom", "type", "actif"], "properties": {"id": {"type": "string", "format": "uuid"}, "nom": {"type": "string"}, "type": {"type": "string", "description": "`operateur`, `revendeur` ou `client` ; un autre type désigne la racine de l'éditeur."}, "parent_id": {"type": ["string", "null"], "format": "uuid"}, "actif": {"type": "boolean"}}}, "OuvertureAssistance": {"type": "object", "required": ["heures"], "properties": {"heures": {"type": "integer", "format": "int32", "description": "Durée de l'ouverture, en heures (1 à 168).", "minimum": 0}}}, "PageAudit": {"type": "object", "required": ["entrees"], "properties": {"entrees": {"type": "array", "items": {"$ref": "#/components/schemas/EntreeAudit"}}, "suivant": {"type": ["integer", "null"], "format": "int64", "description": "Rang à passer en `avant` pour la page suivante ; absent : dernière page."}}}, "ParametresMateriel": {"type": "object", "description": "Paramètres supplémentaires d'un client, une ligne `clé = valeur`.", "required": ["parametres"], "properties": {"parametres": {"type": "string"}}}, "Parcours": {"type": "object", "description": "Parcours d'un client : ses modules et leurs liens.", "required": ["modules", "liens"], "properties": {"modules": {"type": "array", "items": {"$ref": "#/components/schemas/Module"}}, "liens": {"type": "array", "items": {"$ref": "#/components/schemas/Lien"}}}}, "Pas": {"type": "string", "description": "Découpage d'une période.", "enum": ["heure", "jour", "semaine", "mois"]}, "PasskeyAjoutee": {"type": "object", "properties": {"codes_de_secours": {"type": ["array", "null"], "items": {"type": "string"}, "description": "Codes de secours, s'il s'agit du premier second facteur du compte (affichés une fois)."}}}, "PaysOrganisation": {"type": "object", "required": ["pays"], "properties": {"pays": {"type": "string", "description": "Code ISO 3166-1 alpha-2, parmi `GET /pays` (`FR`, `BE`, `CH`, `GB`, `US`, `CA`)."}}}, "PaysPrisEnCharge": {"type": "object", "description": "Un pays pris en charge et son plan de numérotation.", "required": ["code", "indicatif", "prefixe_national", "prefixe_international", "urgences"], "properties": {"code": {"type": "string", "description": "Code ISO 3166-1 alpha-2."}, "indicatif": {"type": "string", "description": "Indicatif, sans `+` (`33`, `1`…)."}, "prefixe_national": {"type": "string", "description": "Préfixe national (`0`, `1` dans le plan nord-américain)."}, "prefixe_international": {"type": "string", "description": "Préfixe international (`00`, `011` dans le plan nord-américain)."}, "urgences": {"type": "array", "items": {"type": "string"}, "description": "Numéros d'urgence et services d'urgence : toujours joignables, jamais des postes."}}}, "PeriodeModule": {"type": "string", "description": "Période couverte par un module.", "enum": ["direct", "jour", "24h", "7j", "30j", "mois", "annee"]}, "PlafondClient": {"type": "object", "description": "Plafond d'un client : seuils en vigueur, consommation et limitation.", "required": ["seuil_heure", "seuil_jour", "seuils_du_client", "consommation_heure", "consommation_jour"], "properties": {"seuil_heure": {"type": "integer", "format": "int64", "description": "Seuils en vigueur (ceux du client, sinon ceux de l'instance)."}, "seuil_jour": {"type": "integer", "format": "int64"}, "seuils_du_client": {"$ref": "#/components/schemas/SeuilsDuClient", "description": "Seuils propres au client ; absents : ceux de l'instance."}, "consommation_heure": {"type": "integer", "format": "int64", "description": "Consommation sortante au prix d'achat sur l'heure glissante, depuis la dernière levée."}, "consommation_jour": {"type": "integer", "format": "int64", "description": "Sur le jour glissant, depuis la dernière levée au niveau du jour."}, "limitation": {"oneOf": [{"$ref": "#/components/schemas/LimitationPlafond", "description": "Restriction aux fixes et mobiles du pays du client en cours ; absente : aucune."}, {"type": "null"}]}}}, "Position": {"type": "object", "required": ["x", "y"], "properties": {"x": {"type": "integer", "format": "int32", "minimum": 0}, "y": {"type": "integer", "format": "int32", "minimum": 0}}}, "PremierAcces": {"type": "object", "required": ["jeton", "operateur", "admin_courriel", "admin_nom"], "properties": {"jeton": {"type": "string", "description": "Jeton de l'adresse de mise en route (après le `#`)."}, "operateur": {"type": "string", "description": "Nom de l'opérateur."}, "admin_courriel": {"type": "string", "description": "Adresse e-mail du premier administrateur opérateur."}, "admin_nom": {"type": "string", "description": "Nom du premier administrateur opérateur."}}}, "PremierAccesFait": {"type": "object", "required": ["operateur_id", "invitation"], "properties": {"operateur_id": {"type": "string", "format": "uuid", "description": "L'opérateur créé."}, "invitation": {"type": "string", "description": "Lien d'invitation de l'administrateur (`/invitation#<jeton>`), à ouvrir aussitôt pour\nchoisir son mot de passe, puis son second facteur."}}}, "Probleme": {"type": "object", "description": "Corps de toute réponse d'erreur.", "required": ["code", "detail"], "properties": {"code": {"type": "string", "description": "Code stable de l'erreur (ex. `base_indisponible`), clé de traduction côté portail."}, "detail": {"type": "string", "description": "Détail technique, non destiné à l'affichage tel quel."}}}, "ProfilMateriel": {"type": "object", "description": "Un profil et son contenu.", "required": ["resume", "contenu"], "properties": {"resume": {"$ref": "#/components/schemas/ResumeProfil"}, "contenu": {"$ref": "#/components/schemas/ContenuProfil"}}}, "ProfilTrunk": {"type": "object", "required": ["id", "nom", "proxy", "format", "reseaux", "trunks"], "properties": {"id": {"type": "string", "format": "uuid"}, "nom": {"type": "string", "description": "Nom du fournisseur, repris sur les trunks (« Fournisseur A »)."}, "proxy": {"type": "string", "description": "Adresse du C5 : `hôte` ou `hôte:port`."}, "format": {"$ref": "#/components/schemas/Format"}, "reseaux": {"type": "array", "items": {"type": "string"}, "description": "Réseaux du fournisseur (CIDR), autorisés dans l'ACL."}, "trunks": {"type": "integer", "format": "int64", "description": "Trunks de clients tirés du profil."}}}, "ProfilsMateriel": {"type": "object", "description": "Les profils livrés par Kanadr et les copies de l'opérateur.", "required": ["livres", "copies"], "properties": {"livres": {"type": "array", "items": {"$ref": "#/components/schemas/ResumeProfil"}}, "copies": {"type": "array", "items": {"$ref": "#/components/schemas/ResumeProfil"}}}}, "Publication": {"type": "object", "description": "Résultat d'une publication.", "required": ["version", "ecartes"], "properties": {"version": {"$ref": "#/components/schemas/VersionParcours"}, "ecartes": {"type": "array", "items": {"type": "string"}, "description": "Modules écartés (en erreur, ou menant à un module en erreur) : ils gardent ce qui était\nservi."}}}, "QualiteFournisseur": {"type": "object", "description": "Issue des appels sortants passés par les trunks d'un fournisseur.", "required": ["fournisseur", "appels", "aboutis", "non_decroches", "echecs", "causes"], "properties": {"fournisseur": {"type": "string", "description": "Profil de trunk (D95), sinon fournisseur saisi sur le trunk, sinon son serveur."}, "appels": {"type": "integer", "format": "int64"}, "aboutis": {"type": "integer", "format": "int64", "description": "Décrochés par l'appelé."}, "non_decroches": {"type": "integer", "format": "int64", "description": "Occupé, pas de réponse, ou raccroché par l'appelant avant le décroché."}, "echecs": {"type": "integer", "format": "int64", "description": "Refusés ou en échec dans le réseau."}, "causes": {"type": "array", "items": {"$ref": "#/components/schemas/CauseEchec"}, "description": "Causes des échecs, les plus fréquentes d'abord."}}}, "QuestionAssistant": {"type": "object", "description": "Question à choix posée par l'assistant (D88) : les choix en boutons ; le prochain message de\nl'utilisateur, choix ou réponse libre, y répond.", "required": ["id", "question", "choix"], "properties": {"id": {"type": "string", "description": "Appel d'outil (`tool_use`)."}, "question": {"type": "string"}, "choix": {"type": "array", "items": {"type": "string"}, "description": "Deux à quatre réponses proposées."}}}, "Redemarrage": {"type": "object", "description": "Redémarrage du moteur de téléphonie.", "properties": {"immediat": {"type": "boolean", "description": "`true` : tout de suite, appels en cours coupés ; `false` : dès que plus aucun appel n'est\nen cours (nouveaux appels refusés en attendant)."}}}, "RedirectionOauth": {"type": "object", "description": "Où envoyer le navigateur : l'adresse de retour de l'application, avec le code d'autorisation\nou le refus.", "required": ["redirection"], "properties": {"redirection": {"type": "string"}}}, "RedirectionOidc": {"type": "object", "required": ["url", "libelle"], "properties": {"url": {"type": "string", "description": "Adresse de l'annuaire où envoyer le navigateur."}, "libelle": {"type": "string", "description": "Nom de l'annuaire."}}}, "ReglageAcrobits": {"type": "object", "description": "Application mobile de l'opérateur.", "required": ["cloud_id"], "properties": {"cloud_id": {"type": "string", "description": "Cloud ID Acrobits de l'application (Cloud Softphone) : capitales, chiffres, `-` ou `_`."}}}, "ReglageAssistant": {"type": "object", "required": ["cle_definie", "modele", "budget_instance_centimes", "prix_entree_centimes", "prix_sortie_centimes", "consomme_mois_centimes"], "properties": {"cle_definie": {"type": "boolean", "description": "Une clé est enregistrée (jamais renvoyée)."}, "modele": {"type": "string"}, "budget_instance_centimes": {"type": "integer", "format": "int64", "description": "Budget mensuel de toute l'instance, en centièmes de la devise de l'instance."}, "budget_client_centimes": {"type": ["integer", "null"], "format": "int64", "description": "Budget mensuel de chaque client, en centièmes de la devise de l'instance ; absent : pas\nde limite propre."}, "prix_entree_centimes": {"type": "integer", "format": "int32", "description": "Prix en centièmes de la devise de l'instance par million de tokens."}, "prix_sortie_centimes": {"type": "integer", "format": "int32"}, "consomme_mois_centimes": {"type": "integer", "format": "int64", "description": "Consommé ce mois-ci par toute l'instance, en centièmes de la devise de l'instance."}}}, "ReglageBudget": {"type": "object", "description": "Réglage du budget mensuel.", "properties": {"montant": {"type": ["integer", "null"], "format": "int64", "description": "Montant mensuel HT, en millionièmes de la devise de l'instance ; absent : pas de budget."}, "bloquer": {"type": "boolean", "description": "Au seuil, restreindre les sortants (sinon, seulement alerter)."}}}, "ReglageDevise": {"type": "object", "description": "Devise à régler.", "required": ["devise"], "properties": {"devise": {"type": "string", "description": "Code ISO 4217 : `EUR`, `CHF`, `GBP`, `USD` ou `CAD`."}}}, "ReglageEtape": {"type": "object", "required": ["etat"], "properties": {"etat": {"type": "string", "description": "`a_faire`, `fait` ou `passe`."}}}, "ReglageForfait": {"type": "object", "description": "Réglage d'un forfait ; absent : aucun sur la grille, ou celui de la grille pour un client.", "properties": {"forfait": {"oneOf": [{"$ref": "#/components/schemas/Forfait"}, {"type": "null"}]}}}, "ReglageJournal": {"type": "object", "description": "Réglage du journal d'un client.", "required": ["masquer_numeros"], "properties": {"masquer_numeros": {"type": "boolean", "description": "Numéros externes partiellement masqués (par défaut)."}}}, "ReglageMarque": {"type": "object", "properties": {"nom": {"type": ["string", "null"], "description": "Nom affiché ; absent ou vide : celui de l'opérateur."}, "couleur": {"type": ["string", "null"], "description": "Couleur d'accent `#rrggbb` ; absente : celle par défaut."}, "couleur_menu": {"type": ["string", "null"], "description": "Fond du menu latéral `#rrggbb` (texte et entrée active en sont déduits) ; absent : celui\npar défaut."}, "couleur_texte": {"type": ["string", "null"], "description": "Couleur des textes `#rrggbb` ; absente : celle par défaut."}}}, "ReglageOidc": {"type": "object", "required": ["emetteur", "client_id", "libelle", "domaines", "creation_auto", "redirection"], "properties": {"emetteur": {"type": "string", "description": "Adresse de l'émetteur (`issuer`), en https."}, "client_id": {"type": "string"}, "libelle": {"type": "string", "description": "Nom affiché sur le bouton de connexion."}, "domaines": {"type": "array", "items": {"type": "string"}, "description": "Domaines d'adresse acceptés ; vide : tous."}, "creation_auto": {"type": "boolean", "description": "Client seulement : créer le compte d'une adresse de ses domaines à sa première connexion ;\nsans effet tant que l'opérateur ne laisse pas l'ajout d'utilisateurs au client (D121)."}, "redirection": {"type": "string", "description": "Adresse de retour à déclarer chez l'annuaire."}}}, "ReglageRps": {"type": "object", "description": "Clés RPS de l'opérateur, sans le secret.", "required": ["cle_id", "region", "serveur", "modifie_le"], "properties": {"cle_id": {"type": "string", "description": "`AccessKey ID` de YMCS."}, "region": {"type": "string", "description": "Région du compte YMCS : `eu`, `us` ou `au`."}, "serveur": {"type": "string", "description": "Nom du serveur RPS, créé dans YMCS, qui renvoie les téléphones vers l'instance."}, "modifie_le": {"type": "string", "description": "Dernière modification (RFC 3339)."}}}, "ReglageSmtp": {"type": "object", "required": ["hote", "port", "securite", "mot_de_passe_defini", "expediteur", "nom_expediteur"], "properties": {"hote": {"type": "string"}, "port": {"type": "integer", "format": "int32", "minimum": 0}, "securite": {"type": "string", "description": "`starttls` (587), `tls` (465) ou `aucune` (relais local, 25)."}, "identifiant": {"type": ["string", "null"], "description": "Absent : relais sans authentification."}, "mot_de_passe_defini": {"type": "boolean", "description": "Un mot de passe est enregistré (jamais renvoyé)."}, "expediteur": {"type": "string", "description": "Adresse d'expédition des e-mails."}, "nom_expediteur": {"type": "string", "description": "Nom affiché de l'expéditeur."}}}, "ReglageSsoClient": {"type": "object", "required": ["creation_auto"], "properties": {"creation_auto": {"type": "boolean", "description": "Créer le compte (rôle utilisateur, sans poste) d'une adresse inconnue à sa première\nconnexion par le portail de l'opérateur ; sans effet tant que l'opérateur ne laisse pas\nl'ajout d'utilisateurs au client (D121)."}}}, "ReglageSsoJeton": {"type": "object", "required": ["actif", "audience"], "properties": {"actif": {"type": "boolean", "description": "Une clé est-elle en service ?"}, "cree_le": {"type": ["string", "null"], "format": "date-time", "description": "Création de la clé en service."}, "audience": {"type": "string", "description": "Audience attendue dans les jetons (`aud`) : l'adresse publique du portail."}}}, "ReglageSynthese": {"type": "object", "required": ["moteur", "cle_definie", "voix_fr", "voix_en", "piper", "piper_anglais"], "properties": {"moteur": {"$ref": "#/components/schemas/MoteurSynthese", "description": "`piper` (par défaut) ou `google`."}, "cle_definie": {"type": "boolean", "description": "Une clé d'API Google est enregistrée (jamais renvoyée)."}, "voix_fr": {"type": "string", "description": "Voix Google des clients réglés en français (`fr-FR-Chirp3-HD-Leda`) ; son préfixe donne\nla langue demandée à Google."}, "voix_en": {"type": "string", "description": "Voix Google des clients réglés en anglais (`en-US-Chirp3-HD-Leda`)."}, "piper": {"type": "boolean", "description": "Piper est installé sur ce serveur (moteur par défaut, et secours de Google)."}, "piper_anglais": {"type": "boolean", "description": "La voix anglaise de Piper est installée."}}}, "ReglageTranscription": {"type": "object", "required": ["url", "cle_definie", "modele"], "properties": {"url": {"type": "string", "description": "Adresse de base de l'API, avant `/audio/transcriptions` (`https://api.openai.com/v1`)."}, "cle_definie": {"type": "boolean", "description": "Une clé d'API est enregistrée (jamais renvoyée)."}, "modele": {"type": "string", "description": "Modèle (`whisper-1`, `Systran/faster-whisper-large-v3`…)."}, "langue": {"type": ["string", "null"], "description": "Langue imposée à tous les messages (ISO 639-1) ; absente : celle du client de chaque\nboîte (D81)."}}}, "ReglagesBoite": {"type": "object", "description": "Réglages d'une boîte.", "required": ["active", "courriels", "piece_jointe", "garder_apres_courriel", "transcription"], "properties": {"active": {"type": "boolean"}, "courriels": {"type": "array", "items": {"type": "string"}, "description": "5 adresses au plus."}, "piece_jointe": {"type": "boolean"}, "garder_apres_courriel": {"type": "boolean", "description": "Faux seulement avec au moins une adresse et la pièce jointe : sinon le message serait\nperdu."}, "transcription": {"type": "boolean"}}}, "ReglagesGarde": {"type": "object", "required": ["seuil", "fenetre_secondes", "duree_secondes", "liste_blanche"], "properties": {"seuil": {"type": "integer", "format": "int32", "description": "Échecs qui déclenchent le bannissement (1 à 1000)."}, "fenetre_secondes": {"type": "integer", "format": "int32", "description": "Fenêtre de comptage, en secondes (10 à 86 400)."}, "duree_secondes": {"type": "integer", "format": "int32", "description": "Durée du bannissement, en secondes (60 à 2 592 000)."}, "liste_blanche": {"type": "array", "items": {"$ref": "#/components/schemas/ReseauAutorise"}, "description": "Adresses ou réseaux (CIDR) jamais bannis."}}}, "ReleveLicence": {"type": "object", "required": ["jour", "utilisateurs"], "properties": {"jour": {"type": "string", "description": "Jour relevé (`AAAA-MM-JJ`)."}, "utilisateurs": {"type": "integer", "format": "int64"}, "envoye_le": {"type": ["string", "null"], "format": "date-time", "description": "Accepté par le Hub."}, "erreur": {"type": ["string", "null"], "description": "Dernière erreur d'envoi."}}}, "ReleveMachine": {"type": "object", "description": "Un relevé de la machine.", "required": ["instant", "coeurs", "memoire_totale", "memoire_disponible", "charge"], "properties": {"instant": {"type": "string", "format": "date-time"}, "processeur": {"type": ["number", "null"], "format": "float", "description": "Part du processeur occupée depuis le relevé précédent, de 0 à 1 ; absente au premier\nrelevé après un démarrage."}, "coeurs": {"type": "integer", "format": "int32", "description": "Unités de calcul."}, "memoire_totale": {"type": "integer", "format": "int64"}, "memoire_disponible": {"type": "integer", "format": "int64", "description": "Mémoire disponible sans échanger (le cache disque compte comme disponible)."}, "charge": {"type": "number", "format": "float", "description": "Charge moyenne sur une minute (à rapporter au nombre d'unités)."}, "systeme_taille": {"type": ["integer", "null"], "format": "int64"}, "systeme_libres": {"type": ["integer", "null"], "format": "int64"}, "enregistrements_taille": {"type": ["integer", "null"], "format": "int64", "description": "Volume des enregistrements (D101)."}, "enregistrements_libres": {"type": ["integer", "null"], "format": "int64"}}}, "ReleveSigne": {"type": "object", "description": "Relevé signé, tel qu'envoyé au Hub.", "required": ["contenu", "signature", "cle_publique"], "properties": {"contenu": {"type": "string", "description": "Texte JSON du relevé, signé tel quel."}, "signature": {"type": "string", "description": "Signature Ed25519 du contenu (hexadécimal)."}, "cle_publique": {"type": "string", "description": "Clé publique de l'instance (hexadécimal)."}}}, "Renvoi": {"type": "object", "required": ["ext", "nom", "numero"], "properties": {"ext": {"type": "string"}, "nom": {"type": "string"}, "numero": {"type": "string", "description": "Fixe ou mobile du pays du client, jamais un numéro spécial (règle des renvois de poste,\n[`crate::numerotation::destination_de_renvoi`]) ; les numéros d'autres pays sont refusés."}}}, "RenvoiPoste": {"type": "object", "description": "Un renvoi : actif ou non, et sa destination, gardée quand il est coupé.", "required": ["actif"], "properties": {"actif": {"type": "boolean"}, "destination": {"type": ["string", "null"], "description": "Fixe ou mobile du pays du client (D124), jamais un numéro spécial (en France, jamais un\n08) ni un numéro d'un autre pays : E.164 en réponse ; national, `+` ou préfixe\ninternational suivi de l'indicatif du pays en saisie."}}}, "RenvoisPoste": {"type": "object", "description": "Les quatre renvois d'un poste.", "required": ["tous", "occupe", "sans_reponse", "injoignable"], "properties": {"tous": {"$ref": "#/components/schemas/RenvoiPoste", "description": "Tous les appels : le téléphone ne sonne plus."}, "occupe": {"$ref": "#/components/schemas/RenvoiPoste", "description": "Le poste est déjà en ligne."}, "sans_reponse": {"$ref": "#/components/schemas/RenvoiPoste", "description": "Pas de réponse (avant la messagerie)."}, "injoignable": {"$ref": "#/components/schemas/RenvoiPoste", "description": "Aucun téléphone connecté."}}}, "RepertoireOuvert": {"type": "object", "description": "Répertoire commun ouvert ou non aux collaborateurs du client.", "required": ["actif"], "properties": {"actif": {"type": "boolean", "description": "Les collaborateurs du client peuvent ajouter au répertoire commun (et modifier ou\nsupprimer les contacts qu'ils y ont ajoutés)."}}}, "ReponseAssistant": {"type": "object", "required": ["messages", "budget_atteint"], "properties": {"messages": {"type": "array", "items": {}, "description": "Conversation à jour, à renvoyer telle quelle au prochain message."}, "en_attente": {"oneOf": [{"$ref": "#/components/schemas/ActionEnAttente"}, {"type": "null"}]}, "question": {"oneOf": [{"$ref": "#/components/schemas/QuestionAssistant"}, {"type": "null"}]}, "budget_atteint": {"type": "boolean"}}}, "ReponseDemandeOauth": {"type": "object", "description": "Réponse de l'utilisateur à une demande d'autorisation.", "required": ["accepter"], "properties": {"accepter": {"type": "boolean", "description": "`true` : accorder l'accès ; `false` : le refuser."}}}, "RequeteAppareil": {"type": "object", "description": "Une demande reçue de l'appareil par le service des fichiers.", "required": ["fichier", "statut", "recue_le"], "properties": {"fichier": {"type": "string"}, "statut": {"type": "integer", "format": "int32", "minimum": 0}, "adresse": {"type": ["string", "null"]}, "agent": {"type": ["string", "null"]}, "recue_le": {"type": "string"}}}, "ReseauAutorise": {"type": "object", "required": ["reseau"], "properties": {"reseau": {"type": "string"}, "description": {"type": ["string", "null"]}}}, "Reservation": {"type": "object", "properties": {"revendeur_id": {"type": ["string", "null"], "format": "uuid", "description": "Revendeur ; absent ou `null` : réservation levée."}}}, "RestrictionBudget": {"type": "object", "description": "Restriction posée par le budget.", "required": ["depuis"], "properties": {"depuis": {"type": "string", "format": "date-time"}}}, "RestrictionsPoste": {"type": "object", "required": ["poste", "natures"], "properties": {"poste": {"type": "string"}, "natures": {"type": "array", "items": {"type": "string"}, "description": "`surtaxes`, `international`, `sortants`."}}}, "ResumePasskey": {"type": "object", "required": ["id", "nom", "cree_le"], "properties": {"id": {"type": "string", "format": "uuid"}, "nom": {"type": "string"}, "cree_le": {"type": "string", "format": "date-time"}, "derniere_utilisation": {"type": ["string", "null"], "format": "date-time"}}}, "ResumeProfil": {"type": "object", "description": "Un profil, sans ses gabarits.", "required": ["reference", "nom", "marque", "etiquette", "version", "nouvelle_version", "modeles", "appareils"], "properties": {"reference": {"type": "string", "description": "Identifiant d'un profil livré (`yealink-bureau`) ou uuid d'une copie."}, "nom": {"type": "string"}, "marque": {"type": "string"}, "etiquette": {"type": "string", "description": "`teste`, `communautaire` (profils livrés) ou `copie`."}, "version": {"type": "integer", "format": "int32", "minimum": 0}, "origine": {"type": ["string", "null"], "description": "Profil livré d'origine d'une copie, et sa version au moment de la copie."}, "origine_version": {"type": ["integer", "null"], "format": "int32", "minimum": 0}, "nouvelle_version": {"type": "boolean", "description": "Kanadr livre une version plus récente du profil d'origine."}, "redirection": {"type": ["string", "null"], "description": "Service de redirection de la marque (`yealink-rps`)."}, "modeles": {"type": "array", "items": {"$ref": "#/components/schemas/ModeleMateriel"}}, "appareils": {"type": "integer", "format": "int64", "description": "Appareils qui l'utilisent."}}}, "ResumeVersion": {"type": "object", "description": "Une version publiée, sans son contenu.", "required": ["version", "auteur", "note", "publie_le"], "properties": {"version": {"type": "integer", "format": "int32"}, "auteur": {"type": "string"}, "note": {"type": "string"}, "publie_le": {"type": "string", "format": "date-time"}}}, "Retention": {"type": "object", "required": ["reglees", "appliquees"], "properties": {"reglees": {"$ref": "#/components/schemas/Durees", "description": "Ce qui est réglé sur cette organisation."}, "appliquees": {"$ref": "#/components/schemas/Durees", "description": "Ce qui s'applique, réglages des niveaux au-dessus et valeurs par défaut compris ; `null` :\ngardé sans limite."}}}, "Revendeur": {"type": "object", "required": ["id", "nom", "actif", "clients"], "properties": {"id": {"type": "string", "format": "uuid"}, "nom": {"type": "string"}, "actif": {"type": "boolean"}, "clients": {"type": "integer", "format": "int64", "description": "Nombre de clients qui dépendent du revendeur."}}}, "SaisieContact": {"type": "object", "description": "Entrée à ajouter ou à modifier.", "required": ["nom", "numero"], "properties": {"nom": {"type": "string", "description": "1 à 100 caractères."}, "numero": {"type": "string", "description": "E.164, national (`06…`) ou international en `00` ; espaces, points et tirets ignorés."}}}, "SaisieContactPersonnel": {"type": "object", "description": "Contact personnel à créer ou à modifier.", "required": ["nom", "numeros"], "properties": {"nom": {"type": "string", "description": "1 à 100 caractères."}, "entreprise": {"type": ["string", "null"], "description": "Facultative, 100 caractères au plus."}, "numeros": {"type": "array", "items": {"type": "string"}, "description": "1 à 5 numéros : E.164, national (`06…`) ou international en `00`."}}}, "Sante": {"type": "object", "description": "Santé de l'instance vue par l'organisation (diagnostic).", "required": ["schema", "trunks", "webhooks_abandonnes", "version"], "properties": {"moteur": {"oneOf": [{"$ref": "#/components/schemas/SanteMoteur", "description": "Absent : le moteur de téléphonie ne répond pas."}, {"type": "null"}]}, "schema": {"type": "integer", "format": "int64", "description": "Version du schéma de la base."}, "dernier_cdr": {"type": ["string", "null"], "format": "date-time", "description": "Dernier CDR reçu chez ses clients."}, "trunks": {"type": "array", "items": {"$ref": "#/components/schemas/SanteTrunk"}}, "webhooks_abandonnes": {"type": "integer", "format": "int64", "description": "Envois de webhooks abandonnés ces sept derniers jours, dans sa descendance."}, "version": {"type": "string", "description": "Version installée du produit (paquet Debian, D10)."}, "mise_a_jour": {"type": ["string", "null"], "description": "Version plus récente disponible dans le dépôt apt, à installer par `apt upgrade`."}, "stockage": {"oneOf": [{"$ref": "#/components/schemas/Stockage", "description": "Volume des enregistrements et disque système (D101) ; pour l'opérateur seulement."}, {"type": "null"}]}, "telephone": {"oneOf": [{"$ref": "#/components/schemas/SanteTelephone", "description": "Softphone WebRTC (D107) : `ws-binding` et serveur TURN ; pour l'opérateur seulement."}, {"type": "null"}]}}}, "SanteMoteur": {"type": "object", "description": "État du moteur de téléphonie.", "required": ["version", "appels"], "properties": {"version": {"type": "string"}, "fonctionne_depuis_secondes": {"type": ["integer", "null"], "format": "int64", "description": "Durée de fonctionnement en secondes (première ligne de `status`) ; absente si la ligne\nn'a pas la forme attendue.", "minimum": 0}, "appels": {"type": "integer", "format": "int64", "description": "Appels en cours sur toute l'instance.", "minimum": 0}}}, "SanteTelephone": {"type": "object", "description": "Softphone WebRTC (D107) : ce dont il a besoin sur la machine.", "required": ["websocket", "websocket_ecoute"], "properties": {"websocket": {"type": "string", "description": "Adresse du `ws-binding` du profil `internal` (boucle locale)."}, "websocket_ecoute": {"type": "boolean", "description": "Le `ws-binding` écoute-t-il ? Non : le profil `internal` n'a pas été redémarré depuis son\nactivation (le binaire le fait dès qu'aucun appel n'est en cours)."}, "turn": {"type": ["string", "null"], "description": "Nom d'hôte du serveur TURN ; absent : TURN non réglé, le softphone ne passe pas les\nréseaux qui bloquent l'UDP."}, "turn_ecoute": {"type": ["boolean", "null"], "description": "coturn écoute-t-il sur 3478 ? Absent quand le TURN n'est pas réglé."}}}, "SanteTrunk": {"type": "object", "description": "État du trunk d'un client.", "required": ["client_id", "client"], "properties": {"client_id": {"type": "string", "format": "uuid"}, "client": {"type": "string"}, "enregistrement": {"type": ["string", "null"], "description": "État d'enregistrement selon le moteur de téléphonie (`REGED`, `FAIL_WAIT`…), s'il répond ;\n`NOREG` pour un trunk par adresse IP."}, "dernier_echec": {"oneOf": [{"$ref": "#/components/schemas/EchecEnregistrement", "description": "Dernier refus d'enregistrement du fournisseur (code SIP, motif)."}, {"type": "null"}]}}}, "SauvegardeFaite": {"type": "object", "description": "Dernière sauvegarde faite par `kanadr sauvegarder` (D25).", "required": ["faite_le", "hote", "taille_octets", "schema"], "properties": {"faite_le": {"type": "string", "format": "date-time"}, "hote": {"type": "string"}, "taille_octets": {"type": "integer", "format": "int64"}, "schema": {"type": "integer", "format": "int64", "description": "Version du schéma sauvegardée."}}}, "SecuriteClient": {"type": "object", "required": ["second_facteur_force"], "properties": {"second_facteur_force": {"type": "boolean", "description": "Second facteur imposé à tous les comptes du client, admins compris."}}}, "ServeurIce": {"type": "object", "description": "Serveur ICE (STUN ou TURN), tel que le navigateur l'attend (`RTCIceServer`).", "required": ["urls"], "properties": {"urls": {"type": "array", "items": {"type": "string"}, "description": "Adresses (`stun:`, `turn:`, `turns:`)."}, "identifiant": {"type": ["string", "null"], "description": "Identifiant TURN éphémère (`username`)."}, "mot_de_passe": {"type": ["string", "null"], "description": "Mot de passe TURN éphémère (`credential`)."}}}, "SessionExportee": {"type": "object", "required": ["ouverte_le", "expire_le"], "properties": {"ouverte_le": {"type": "string", "format": "date-time"}, "expire_le": {"type": "string", "format": "date-time"}, "adresse_ip": {"type": ["string", "null"]}, "agent": {"type": ["string", "null"]}}}, "SeuilsDuClient": {"type": "object", "description": "Seuils propres à un client ; absents : ceux de l'instance.", "properties": {"seuil_heure": {"type": ["integer", "null"], "format": "int64"}, "seuil_jour": {"type": ["integer", "null"], "format": "int64"}}}, "SeuilsPlafond": {"type": "object", "description": "Seuils de consommation, en millionièmes de la devise de l'instance, HT, au prix d'achat.", "required": ["seuil_heure", "seuil_jour"], "properties": {"seuil_heure": {"type": "integer", "format": "int64", "description": "Sur une heure glissante."}, "seuil_jour": {"type": "integer", "format": "int64", "description": "Sur un jour glissant."}}}, "Simultanes": {"type": "object", "description": "Appels simultanés heure par heure sur une période.", "required": ["heures", "pic"], "properties": {"heures": {"type": "array", "items": {"$ref": "#/components/schemas/HeureSimultanee"}, "description": "Chaque heure de la période, même sans appel."}, "pic": {"type": "integer", "format": "int64", "description": "Plus haut pic de la période."}}}, "Sip": {"type": "object", "required": ["ext", "nom", "hote", "identifiant", "numero_sip"], "properties": {"ext": {"type": "string"}, "nom": {"type": "string"}, "hote": {"type": "string", "description": "Hôte du service, port facultatif (`voip.exemple.fr`, `voip.exemple.fr:5080`)."}, "identifiant": {"type": "string", "description": "Identifiant de l'enregistrement."}, "numero_sip": {"type": "string", "description": "Numéro SIP à appeler chez le service : une adresse du service, pas forcément un numéro\njoignable (`+33112…`)."}}}, "StatistiquesClient": {"type": "object", "description": "Statistiques des appels reçus d'un client.", "required": ["jours", "chaleur"], "properties": {"jours": {"type": "array", "items": {"$ref": "#/components/schemas/JourClient"}, "description": "Chaque jour de la période, même sans appel."}, "chaleur": {"type": "array", "items": {"$ref": "#/components/schemas/CaseChaleur"}, "description": "Les 168 cases de la semaine (7 jours × 24 heures), même vides."}}}, "StatistiquesParc": {"type": "object", "description": "Statistiques du parc d'un opérateur ou d'un revendeur.", "required": ["jours", "fournisseurs"], "properties": {"jours": {"type": "array", "items": {"$ref": "#/components/schemas/JourParc"}, "description": "Chaque jour de la période, même sans appel."}, "fournisseurs": {"type": "array", "items": {"$ref": "#/components/schemas/QualiteFournisseur"}, "description": "Fournisseurs, du plus grand nombre d'appels sortants au plus petit."}}}, "StatutMessage": {"type": "object", "description": "Nouveau statut d'un message.", "required": ["lu"], "properties": {"lu": {"type": "boolean"}}}, "Stockage": {"type": "object", "properties": {"enregistrements": {"oneOf": [{"$ref": "#/components/schemas/Volume", "description": "Volume des enregistrements d'appels ; absent s'il est illisible."}, {"type": "null"}]}, "systeme": {"oneOf": [{"$ref": "#/components/schemas/Volume", "description": "Disque système (base, messagerie, journaux) ; absent s'il est illisible."}, {"type": "null"}]}}}, "Strategie": {"type": "string", "enum": ["simultane", "sequence"]}, "SuffixeDomaine": {"type": "object", "description": "Suffixe des domaines clients de l'instance (D108).", "properties": {"suffixe": {"type": ["string", "null"], "description": "Sous-domaine de l'opérateur (`voip.operateur.fr`) : un client créé avec son seul\nidentifiant (`client`) reçoit `client.voip.operateur.fr`. Absent : domaine complet à\nchaque création."}}}, "Svi": {"type": "object", "required": ["ext", "nom"], "properties": {"ext": {"type": "string"}, "nom": {"type": "string"}}}, "SyntheseAppels": {"type": "object", "description": "Chiffres d'une période (tuiles du portail de la production) : appels entrants et sortants,\nleur durée décrochée, les entrants manqués (ni mis en relation ni message, D66), les messages\nlaissés et le temps moyen avant la mise en relation.", "required": ["entrants", "entrants_secondes", "entrants_non_repondus", "entrants_messages", "sortants", "sortants_secondes", "internes", "mises_en_relation", "mises_en_relation_secondes", "tarife", "sous_revendeur"], "properties": {"entrants": {"type": "integer", "format": "int64"}, "entrants_secondes": {"type": "integer", "format": "int64", "description": "Secondes décrochées des appels entrants."}, "entrants_non_repondus": {"type": "integer", "format": "int64", "description": "Entrants manqués : ni mis en relation avec une personne, ni message (D66)."}, "entrants_messages": {"type": "integer", "format": "int64", "description": "Entrants où l'appelant a laissé un message."}, "reponse_moyenne_secondes": {"type": ["integer", "null"], "format": "int64", "description": "Secondes moyennes entre l'arrivée d'un entrant et sa mise en relation ; absent sans appel\nrépondu."}, "sortants": {"type": "integer", "format": "int64", "description": "Sortants des postes, hors mises en relation (qu'ils compteraient deux fois)."}, "sortants_secondes": {"type": "integer", "format": "int64"}, "internes": {"type": "integer", "format": "int64"}, "mises_en_relation": {"type": "integer", "format": "int64", "description": "Mises en relation : sortants d'un renvoi vers l'extérieur (D104)."}, "mises_en_relation_secondes": {"type": "integer", "format": "int64", "description": "Secondes en relation avec le correspondant."}, "tarife": {"type": "boolean", "description": "Le client a une grille de vente (la sienne, sinon celle par défaut) : ses appels sortants\nsont valorisés (D13)."}, "sous_revendeur": {"type": "boolean", "description": "Le client dépend d'un revendeur ; indiqué seulement à qui voit la vente au revendeur."}, "montant_achat": {"type": ["integer", "null"], "format": "int64", "description": "Totaux de la période, en millionièmes de la devise de l'instance, HT, selon le rôle (comme\nles appels) : achat (opérateur), vente au revendeur (opérateur, revendeur), vente au client (tous)."}, "montant_revendeur": {"type": ["integer", "null"], "format": "int64"}, "montant_client": {"type": ["integer", "null"], "format": "int64"}, "marge": {"type": ["integer", "null"], "format": "int64", "description": "Marge de l'opérateur sur la période : sa vente (au revendeur, sinon au client) moins\nl'achat, sur les appels valorisés des deux côtés ; opérateur seulement."}}}, "Tableau": {"type": "object", "description": "Tableau de bord d'une organisation sur une période.", "required": ["pas", "du", "au", "totaux", "tranches", "destinations", "clients"], "properties": {"pas": {"$ref": "#/components/schemas/Pas"}, "du": {"type": "string", "format": "date-time"}, "au": {"type": "string", "format": "date-time"}, "totaux": {"$ref": "#/components/schemas/Totaux"}, "precedent": {"oneOf": [{"$ref": "#/components/schemas/Totaux", "description": "Période précédente de même longueur, si elle est demandée (`comparer`)."}, {"type": "null"}]}, "tranches": {"type": "array", "items": {"$ref": "#/components/schemas/Tranche"}, "description": "Chaque tranche de la période, même vide."}, "destinations": {"type": "array", "items": {"$ref": "#/components/schemas/DestinationTableau"}, "description": "Sortants décrochés par catégorie de destination, du plus grand nombre d'appels au plus\npetit."}, "clients": {"type": "array", "items": {"$ref": "#/components/schemas/ClientTableau"}, "description": "Clients qui consomment le plus (ventes, sinon appels) ; vide pour un client."}}}, "TailleModule": {"type": "string", "description": "Taille d'un module sur la grille standard de 12 colonnes, rangées de hauteur fixe.", "enum": ["S", "M", "L", "XL"]}, "TarifsClient": {"type": "object", "description": "Tarifs d'un client (D96) : la grille de vente qui valorise ses appels aujourd'hui, en lecture.", "required": ["nom", "effet", "lignes"], "properties": {"nom": {"type": "string", "description": "Nom de la grille."}, "effet": {"type": "string", "format": "date"}, "lignes": {"type": "array", "items": {"$ref": "#/components/schemas/LigneTarifaire"}, "description": "Lignes, par préfixe."}}}, "Texte": {"type": "object", "required": ["texte"], "properties": {"texte": {"type": "string", "description": "Message à lire, 1500 caractères au plus. « 9h », numéros, adresses et « € » sont\nréécrits pour la voix Piper ; la voix Google reçoit le texte tel quel."}, "poste": {"type": ["string", "null"], "description": "Annonce de la boîte vocale de ce poste : la permission `messagerie.regler` sur le poste\nsuffit (le titulaire règle sa messagerie) ; sinon `parcours.modifier`."}}}, "Totaux": {"type": "object", "description": "Appels et montants d'une tranche ou d'une période. Montants en millionièmes de la devise de l'instance, HT ;\nabsents quand le compte ne les voit pas.", "required": ["entrants", "sortants", "internes", "valorises", "secondes_facturees"], "properties": {"entrants": {"type": "integer", "format": "int64"}, "sortants": {"type": "integer", "format": "int64", "description": "Sortants, mises en relation comprises (D104)."}, "internes": {"type": "integer", "format": "int64"}, "valorises": {"type": "integer", "format": "int64", "description": "Sortants décrochés et valorisés."}, "secondes_facturees": {"type": "integer", "format": "int64"}, "ventes": {"type": ["integer", "null"], "format": "int64", "description": "Ce que l'organisation vend (pour un client : ce qu'il dépense)."}, "achats": {"type": ["integer", "null"], "format": "int64", "description": "Ce que l'organisation achète ; absent pour un client."}, "marge": {"type": ["integer", "null"], "format": "int64"}}}, "TotauxNatures": {"type": "object", "description": "Totaux des trois natures de montant, en millionièmes de la devise de l'instance, HT (vide\ncompté 0).", "required": ["achat", "revendeur", "client"], "properties": {"achat": {"type": "integer", "format": "int64"}, "revendeur": {"type": "integer", "format": "int64"}, "client": {"type": "integer", "format": "int64"}}}, "ToucheAppareil": {"type": "object", "description": "Une touche programmable d'un appareil.", "required": ["position", "nature", "valeur", "libelle"], "properties": {"position": {"type": "integer", "format": "int32", "minimum": 0}, "nature": {"type": "string", "description": "`ligne`, `supervision` ou `numero_abrege`."}, "valeur": {"type": "string", "description": "Poste supervisé, numéro abrégé (E.164 ou poste) ou rang de la ligne."}, "libelle": {"type": "string"}, "ligne": {"type": "integer", "format": "int32", "description": "Compte qui l'utilise (1 par défaut).", "minimum": 0}}}, "TraceAppel": {"type": "object", "description": "Trace d'un appel.", "required": ["etapes", "applications", "cause"], "properties": {"etapes": {"type": "array", "items": {"$ref": "#/components/schemas/EtapeTrace"}}, "applications": {"type": "array", "items": {"$ref": "#/components/schemas/ApplicationTrace"}}, "cause": {"type": "string", "description": "`hangup_cause` du moteur de téléphonie."}, "code_sip": {"type": ["string", "null"], "description": "Dernier code SIP de fin."}, "raccroche": {"type": ["string", "null"], "description": "`recv_bye` : le correspondant a raccroché ; `send_bye` : nous."}, "mis_en_relation_avec": {"type": ["string", "null"]}, "cause_relation": {"type": ["string", "null"]}, "codecs": {"type": ["string", "null"]}, "ip_distante": {"type": ["string", "null"]}, "logiciel_distant": {"type": ["string", "null"]}}}, "Tranche": {"allOf": [{"$ref": "#/components/schemas/Totaux"}, {"type": "object", "required": ["debut"], "properties": {"debut": {"type": "string", "format": "date-time"}}}], "description": "Une tranche de la période."}, "Trunk": {"type": "object", "required": ["client_id", "passerelle_uuid", "fournisseur", "proxy", "mot_de_passe_defini", "format", "reseaux"], "properties": {"client_id": {"type": "string", "format": "uuid"}, "passerelle_uuid": {"type": "string", "format": "uuid", "description": "Passerelle SIP du trunk (son nom dans le moteur de téléphonie)."}, "profil_id": {"type": ["string", "null"], "format": "uuid", "description": "Profil de trunk dont il est tiré (D95) ; absent : trunk saisi en entier."}, "fournisseur": {"type": "string"}, "proxy": {"type": "string"}, "identifiant": {"type": ["string", "null"]}, "mot_de_passe_defini": {"type": "boolean", "description": "Un mot de passe est enregistré (jamais renvoyé)."}, "format": {"$ref": "#/components/schemas/Format"}, "reseaux": {"type": "array", "items": {"type": "string"}}, "ndi": {"type": ["string", "null"], "description": "NDI (D48), s'il est encore un numéro du client."}, "enregistrement": {"type": ["string", "null"], "description": "État d'enregistrement auprès du C5 selon le moteur de téléphonie (`REGED`, `FAILED`…),\ns'il répond."}, "dernier_echec": {"oneOf": [{"$ref": "#/components/schemas/EchecEnregistrement", "description": "Dernier refus d'enregistrement du C5 depuis la dernière écriture du trunk."}, {"type": "null"}]}}}, "UtilisateurClient": {"type": "object", "required": ["id", "courriel", "nom", "role", "actif", "telephone_seulement"], "properties": {"id": {"type": "string", "format": "uuid"}, "courriel": {"type": "string"}, "nom": {"type": "string"}, "role": {"type": "string"}, "actif": {"type": "boolean"}, "poste": {"type": ["string", "null"], "description": "Numéro de poste, s'il en a un."}, "telephone_seulement": {"type": "boolean", "description": "Compte « téléphone seulement » (D107) : sa session n'ouvre que le softphone."}, "invitation_envoyee": {"type": ["boolean", "null"], "description": "À la création seulement : l'invitation est-elle partie par e-mail ? `false` sans serveur\nd'e-mails réglé, ou si le serveur l'a refusée (à renvoyer par\n`POST /utilisateurs/{id}/invitation`)."}}}, "UtilisateursClient": {"type": "object", "required": ["client_id", "nom", "utilisateurs"], "properties": {"client_id": {"type": "string", "format": "uuid"}, "nom": {"type": "string"}, "utilisateurs": {"type": "integer", "format": "int64"}}}, "Validation": {"type": "object", "description": "Résultat de la validation.", "required": ["globales", "par_module", "ecartes"], "properties": {"globales": {"type": "array", "items": {"$ref": "#/components/schemas/Erreur"}, "description": "Erreurs qui empêchent toute publication."}, "par_module": {"type": "object", "description": "Erreurs propres à un module, par identifiant (le module est écarté).", "additionalProperties": {"type": "array", "items": {"$ref": "#/components/schemas/Erreur"}}, "propertyNames": {"type": "string"}}, "ecartes": {"type": "array", "items": {"type": "string"}, "description": "Modules écartés : en erreur, ou menant à un module en erreur. Ils gardent ce qui est\nservi aujourd'hui.", "uniqueItems": true}}}, "Verification": {"type": "object", "description": "Ce que vaut un parcours face à la situation du client : validation et changements par\nrapport à la version publiée.", "required": ["validation", "diff"], "properties": {"validation": {"$ref": "#/components/schemas/Validation"}, "diff": {"$ref": "#/components/schemas/Diff"}}}, "VersionParcours": {"type": "object", "description": "Une version publiée.", "required": ["version", "contenu", "auteur", "note", "publie_le"], "properties": {"version": {"type": "integer", "format": "int32"}, "contenu": {"$ref": "#/components/schemas/Parcours"}, "auteur": {"type": "string", "description": "Nom de l'auteur ; vide pour une reprise automatique."}, "note": {"type": "string"}, "publie_le": {"type": "string", "format": "date-time"}}}, "VersionProfil": {"type": "object", "description": "Une version enregistrée d'une copie.", "required": ["version", "nom", "auteur", "resume", "cree_le"], "properties": {"version": {"type": "integer", "format": "int32", "minimum": 0}, "nom": {"type": "string"}, "auteur": {"type": "string"}, "resume": {"type": "string"}, "cree_le": {"type": "string"}}}, "VoixDuClient": {"type": "object", "description": "La voix des annonces d'un client.", "required": ["langue"], "properties": {"voix": {"type": ["string", "null"], "description": "Voix choisie par le client ; absente : la voix de l'instance."}, "langue": {"type": "string", "description": "Langue des annonces, celle du client : `fr` ou `en`."}, "instance": {"oneOf": [{"$ref": "#/components/schemas/VoixSynthese", "description": "Voix de l'instance pour cette langue ; absente si l'instance n'en a aucune."}, {"type": "null"}]}, "utilisee": {"oneOf": [{"$ref": "#/components/schemas/VoixSynthese", "description": "Voix qui lit les annonces saisies en texte ; absente si aucune n'est installée."}, {"type": "null"}]}, "repli": {"type": ["string", "null"], "description": "La voix choisie n'est pas retenue et la voix de l'instance la remplace :\n`voix_indisponible` (l'instance ne l'offre plus) ou `voix_autre_langue` (elle n'est pas\nde la langue du client)."}}}, "VoixSynthese": {"type": "object", "description": "Une voix de l'instance.", "required": ["id", "moteur", "nom", "libelle"], "properties": {"id": {"type": "string", "description": "Identifiant à enregistrer : `piper:fr_FR-siwis-medium`, `google:fr-FR-Chirp3-HD-Leda`."}, "moteur": {"$ref": "#/components/schemas/MoteurSynthese", "description": "`piper` (sur le serveur) ou `google` (Google Cloud Text-to-Speech, clé de l'opérateur)."}, "nom": {"type": "string", "description": "Nom chez le moteur : modèle Piper ou voix Google."}, "libelle": {"type": "string", "description": "Nom court à montrer (`Siwis`, `Leda`)."}, "region": {"type": ["string", "null"], "description": "Région de la voix (`fr-FR`, `en-GB`), si son nom la donne."}}}, "Volume": {"type": "object", "required": ["taille_octets", "libres_octets", "dedie"], "properties": {"taille_octets": {"type": "integer", "format": "int64", "minimum": 0}, "libres_octets": {"type": "integer", "format": "int64", "description": "Octets disponibles.", "minimum": 0}, "dedie": {"type": "boolean", "description": "Son propre système de fichiers (enregistrements) : plein, il ne remplit pas le disque\nsystème."}}}, "Webhook": {"type": "object", "description": "L'endpoint d'une organisation, sans son secret.", "required": ["url", "evenements", "actif", "echecs"], "properties": {"url": {"type": "string"}, "evenements": {"type": "array", "items": {"type": "string"}}, "actif": {"type": "boolean"}, "echecs": {"type": "integer", "format": "int32", "description": "Échecs consécutifs (20 désactivent l'endpoint)."}, "desactive_le": {"type": ["string", "null"], "format": "date-time", "description": "Désactivé automatiquement à cet instant, après 20 échecs consécutifs."}}}, "WebhookAvecSecret": {"allOf": [{"$ref": "#/components/schemas/Webhook"}, {"type": "object", "required": ["secret"], "properties": {"secret": {"type": "string", "description": "64 caractères hexadécimaux ; signe les envois (`X-Webhook-Signature`)."}}}], "description": "Endpoint créé ou secret renouvelé : le secret, affiché cette fois seulement."}}, "securitySchemes": {"cle_api": {"type": "http", "scheme": "bearer", "description": "Clé d'API (`cx_…`), sauf pour gérer les clés."}, "session": {"type": "apiKey", "in": "cookie", "name": "session"}}}, "tags": [{"name": "exploitation", "description": "État de l'instance"}, {"name": "connexion", "description": "Connexion, session et mot de passe"}, {"name": "clients", "description": "Clients finaux, leurs utilisateurs et postes"}, {"name": "organisations", "description": "Revendeurs de l'opérateur, comptes d'équipe de l'opérateur et des revendeurs (D7)"}, {"name": "numeros", "description": "Stock de numéros, réservation, affectation et destination (D28, D40)"}, {"name": "parcours", "description": "Parcours des appels d'un client : brouillon, vérification, publication, versions"}, {"name": "garde", "description": "Bannissement d'IP : réglages, adresses bannies, déblocage (D23, D43)"}, {"name": "trunks", "description": "Trunk C5 d'un client, profils de trunk de l'opérateur et restrictions d'appel des postes (D38, D42, D95)"}, {"name": "cles-api", "description": "Clés d'API : comptes de service à droits restreints"}, {"name": "oauth", "description": "Applications autorisées par un compte à utiliser le serveur MCP avec ses droits (OAuth 2.1, D105)"}, {"name": "webhooks", "description": "Webhooks sortants : endpoint, secret, envois ; CSV du mois par lien signé (D61)"}, {"name": "enregistrements", "description": "Enregistrements d'appels : liste, écoute, export ZIP, suppression (D62)"}, {"name": "repertoire", "description": "Répertoire commun du client : contacts partagés par ses postes"}, {"name": "provisionnement", "description": "Installation des téléphones : liens d'un poste, lien par e-mail (D35)"}, {"name": "materiel", "description": "Téléphones de bureau : profils de matériel de l'opérateur, appareils des clients (D115)"}, {"name": "diagnostic", "description": "Diagnostic (D5) : trace d'un appel, appels en cours, actions tracées"}, {"name": "journal", "description": "Journal d'appels d'un client : appels valorisés, masquage des numéros (D20, D60)"}, {"name": "grilles", "description": "Grilles tarifaires : achat, vente au revendeur, vente au client ; attribution (D13, D59)"}, {"name": "messagerie", "description": "Boîtes vocales des postes : réglages, annonce d'accueil, messages (D37, D56, D57)"}]}