{"openapi":"3.0.1","info":{"title":"🎫 Support Client API","description":"## API de Gestion de Support Technique Multi-Projets\n\nCette API permet de gérer un système complet de tickets de support avec :\n\n### ✨ Fonctionnalités Principales\n- 🎫 **Gestion de Tickets** : Création, mise à jour, assignation automatique\n- 👥 **Multi-Projets** : Organisation par projets avec tags spécifiques\n- 🏷️ **Système de Tags** : Catégorisation intelligente des tickets\n- 📧 **Intégration Email** : Création automatique depuis les emails\n- 🔐 **Sécurité JWT** : Authentification robuste avec rôles\n- 📊 **Statistiques** : Tableaux de bord et analytics\n- 🔔 **Notifications** : Alertes automatiques aux agents\n\n### 🚀 Attribution Automatique\nLe système attribue intelligemment les tickets selon :\n- **Tags métier** : database → OPERATIONS, security → SECURITY\n- **Charge de travail** : Distribution équitable\n- **Compétences** : Matching automatique par rôles\n\n### 🔑 Authentification\n- **JWT Bearer Token** pour les utilisateurs connectés\n- **Marketplace Token** pour l'API externe (Header: X-Marketplace-Token)\n\n### 📱 Utilisation\n1. Authentifiez-vous via `/api/auth/login`\n2. Utilisez le token JWT dans le header Authorization\n3. Explorez les endpoints selon vos permissions\n","contact":{"name":"🛠️ Support Team","url":"https://systalink.fr","email":"support@systalink.fr"},"license":{"name":"MIT License","url":"https://opensource.org/licenses/MIT"},"version":"1.0.0"},"externalDocs":{"description":"📚 Documentation complète du projet","url":"https://github.com/systalink/SupportClient/blob/main/README.md"},"servers":[{"url":"https://support-api.systalink.com","description":"🌐 Serveur de Production"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"🎫 Tickets","description":"Gestion complète des tickets de support"},{"name":"📎 Attachments","description":"Gestion des fichiers attachés"},{"name":"💬 Messages","description":"Messages et communications sur les tickets"},{"name":"🗨️ External Chat API","description":"API de chat en temps réel pour plateformes externes"},{"name":"👥 Users","description":"Gestion des utilisateurs et agents"},{"name":"📚 Documentation","description":"## Documentation et Aide de l'API\n\nEndpoints utiles pour comprendre et utiliser l'API :\n- 🚀 **Guide de démarrage**\n- 📋 **Exemples d'utilisation**\n- ❌ **Codes d'erreur**\n- 🔐 **Permissions et rôles**\n- 📊 **Format des réponses**\n"},{"name":"📸 Profile Pictures","description":"## Gestion des photos de profil\n\n**🔓 Accès public** : Aucune authentification requise\n\n### Fonctionnalités\n- 📸 Récupération de photos de profil\n- 🖼️ Support des formats : JPEG, PNG, GIF, WebP\n- 🔒 Pas d'exposition d'informations sensibles\n- ⚡ Mise en cache optimisée\n"},{"name":"🏢 Projects","description":"Gestion des projets et organisation"},{"name":"� External API","description":"## API Externe pour la Marketplace\n\n### 🔑 Authentification\nUtilisez le header `X-Marketplace-Token` avec un token Base64 contenant l'email du client :\n```json\n{\"email\": \"client@example.com\"}\n```        ### 🎯 Fonctionnalités\n- ✅ **Création de tickets** avec gestion automatique des clients\n- 🔍 **Récupération de tickets** existants\n- 👥 **Vérification d'existence** des clients\n- 🤖 **Détection automatique** de projets basée sur les tags\n- 📊 **Statistiques** des tickets par client\n- 📝 **Support des notes** client personnalisées\n\n### 🌐 Endpoints Disponibles\n- `POST /api/external/tickets/create-and-retrieve` : Créer un ticket\n- `GET /api/external/tickets/{id}` : Récupérer un ticket\n- `GET /api/external/tickets` : Lister les tickets d'un client\n- `GET /api/external/clients/check` : Vérifier un client\n- `POST /api/external/projects/detect` : Détecter un projet\n- `GET /api/external/tickets/statistics` : Statistiques client\n\n### 🏷️ Détection Automatique de Projet\n**Pas besoin de spécifier un projectId !** Le système détecte automatiquement\nle projet approprié en analysant les tags fournis dans la requête.\n\n**Exemples de tags :**\n- `[\"database\", \"mysql\"]` → Projet Base de Données\n- `[\"website\", \"css\", \"javascript\"]` → Projet Site Web\n- `[\"mobile\", \"android\", \"ios\"]` → Projet Mobile\n- `[\"api\", \"rest\", \"integration\"]` → Projet API\n"},{"name":"🔐 Authentication","description":"## Gestion de l'authentification et des sessions\n\nCe module gère :\n- 🔑 **Connexion** avec email/mot de passe\n- 👤 **Inscription** de nouveaux utilisateurs avec photo (admin seulement)\n- 🚪 **Déconnexion** sécurisée\n- 🎫 **Génération de tokens JWT**\n- 📸 **Upload de photo de profil**\n\n### 🔒 Sécurité\n- Tokens JWT avec expiration (24h par défaut)\n- Hashage sécurisé des mots de passe (BCrypt)\n- Validation stricte des entrées\n- Gestion des rôles et permissions\n- Validation des images (taille, format)\n"},{"name":"📚 Base de Connaissances","description":"Gestion des articles de la base de connaissances pour la résolution de problèmes"},{"name":"🔐 Authentication","description":"Endpoints d'authentification et gestion des sessions"},{"name":"🏢 Projects","description":"Gestion des projets et affectation des agents"},{"name":"🏷️ Tags","description":"Tags de catégorisation par projet"},{"name":"👥 Users","description":"## Gestion des utilisateurs\n\n### Fonctionnalités\n- 📝 Mise à jour des informations utilisateur\n- 📸 Gestion des photos de profil\n- 🔒 Sécurité par rôles\n"},{"name":"🔔 Notifications","description":"Système de notifications"},{"name":"🔑 API Keys","description":"Gestion des clés API pour l'authentification"},{"name":"📊 Statistics","description":"Statistiques et rapports analytiques"},{"name":"📧 Email","description":"Gestion et intégration email"},{"name":"🌐 Platform API","description":"API pour les plateformes externes (PAXITY, GESTION_IMMO, Devigen etc.)"},{"name":"🌐 External API","description":"API externe pour marketplace et intégrations"},{"name":"🏷️ Project Tags","description":"Gestion des tags par projet"}],"paths":{"/api/users/{id}":{"get":{"tags":["👥 Users"],"summary":"🔍 Détails d'un utilisateur","description":"Récupère les détails d'un utilisateur spécifique (Admin uniquement)","operationId":"getUserById","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/User"}}}}}},"put":{"tags":["👥 Users"],"summary":"✏️ Modifier un utilisateur (sans photo)","description":"Modifie les informations d'un utilisateur (Admin uniquement)","operationId":"updateUser","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/User"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/User"}}}}}},"delete":{"tags":["👥 Users"],"summary":"🗑️ Supprimer un utilisateur (intelligent)","operationId":"deleteUser","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/users/{id}/with-photo":{"put":{"tags":["👥 Users"],"summary":"📸 Modifier un utilisateur avec photo","description":"### Modification complète d'un utilisateur avec photo de profil\n\n**🔒 Accès :**\n- Administrateurs (tous les utilisateurs)\n- Utilisateurs connectés (leurs propres informations)\n\n**Fonctionnalités :**\n- Mise à jour des informations personnelles\n- Changement de photo de profil\n- Suppression de l'ancienne photo\n\n**Formats d'image acceptés :** JPEG, PNG, GIF, WebP\n**Taille maximale :** 5MB\n","operationId":"updateUserWithPhoto","parameters":[{"name":"id","in":"path","description":"ID de l'utilisateur","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"removePhoto","in":"query","description":"Supprimer la photo actuelle","required":false,"schema":{"type":"boolean","default":false}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"required":["userData"],"type":"object","properties":{"userData":{"type":"string","description":"Données utilisateur (JSON)"},"profilePicture":{"type":"string","description":"Nouvelle photo de profil (optionnelle)","format":"binary"}}}}}},"responses":{"404":{"description":"❌ Utilisateur non trouvé","content":{"application/json":{"schema":{"type":"object"}}}},"200":{"description":"✅ Utilisateur modifié avec succès","content":{"application/json":{"schema":{"type":"object"}}}},"403":{"description":"🚫 Accès refusé","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"❌ Erreur de validation","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"bearerAuth":[]}]}},"/api/users/{id}/profile-picture":{"put":{"tags":["👥 Users"],"summary":"📸 Changer uniquement la photo de profil","description":"### Modification de la photo de profil uniquement\n\n**🔒 Accès :**\n- Administrateurs (tous les utilisateurs)\n- Utilisateurs connectés (leur propre photo)\n\n**Actions possibles :**\n- Uploader une nouvelle photo\n- Supprimer la photo actuelle\n","operationId":"updateProfilePicture","parameters":[{"name":"id","in":"path","description":"ID de l'utilisateur","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"remove","in":"query","description":"Supprimer la photo actuelle","required":false,"schema":{"type":"boolean","default":false}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"profilePicture":{"type":"string","description":"Nouvelle photo de profil","format":"binary"}}}}}},"responses":{"404":{"description":"❌ Utilisateur non trouvé","content":{"application/json":{"schema":{"type":"object"}}}},"200":{"description":"✅ Photo mise à jour avec succès","content":{"application/json":{"schema":{"type":"object"}}}},"403":{"description":"🚫 Accès refusé","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"❌ Erreur de validation","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"bearerAuth":[]}]}},"/api/tickets/{id}":{"get":{"tags":["ticket-controller"],"operationId":"getTicketById","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}},"put":{"tags":["ticket-controller"],"operationId":"updateTicket","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TicketRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}},"delete":{"tags":["ticket-controller"],"operationId":"deleteTicket","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/settings/user/{key}":{"get":{"tags":["settings-controller"],"operationId":"getUserSetting","parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}},"put":{"tags":["settings-controller"],"operationId":"updateUserSetting","parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"}}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/settings/global/{key}":{"get":{"tags":["settings-controller"],"operationId":"getGlobalSetting","parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}},"put":{"tags":["settings-controller"],"operationId":"updateGlobalSetting","parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"}}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/projects/{projectId}/tags/{tagId}":{"put":{"tags":["🏷️ Project Tags"],"summary":"✏️ Mettre à jour un tag","description":"Met à jour les informations d'un tag existant.\n\n### 🔐 Permissions\nRéservé aux administrateurs (ADMIN uniquement)\n\n### 📝 Modifications possibles\n- Changement du nom (avec validation d'unicité)\n- Modification de la couleur\n\n### ⚠️ Contraintes\n- Le tag doit appartenir au projet spécifié\n- Le nouveau nom ne doit pas déjà exister dans le projet\n","operationId":"updateProjectTag","parameters":[{"name":"projectId","in":"path","description":"ID du projet","required":true,"schema":{"type":"integer","format":"int64"},"example":1},{"name":"tagId","in":"path","description":"ID du tag à modifier","required":true,"schema":{"type":"integer","format":"int64"},"example":5}],"requestBody":{"description":"Nouvelles données du tag","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"}},"example":{"name":"optimization","color":"#E74C3C"}}},"required":true},"responses":{"200":{"description":"✅ Tag mis à jour","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Tag"}}}},"400":{"description":"❌ Erreur de validation ou tag ne appartient pas au projet","content":{"application/json":{"schema":{"type":"object"}}}},"404":{"description":"❌ Tag non trouvé","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"bearerAuth":[]}]},"delete":{"tags":["🏷️ Project Tags"],"summary":"🗑️ Supprimer un tag","description":"Supprime un tag d'un projet.\n\n### 🔐 Permissions\nRéservé aux administrateurs (ADMIN uniquement)\n\n### ⚠️ Vérifications de sécurité\n- Le tag doit appartenir au projet spécifié\n- Le tag ne doit pas être utilisé par des tickets existants\n\n### 💡 Protection des données\nSi le tag est utilisé par des tickets, la suppression est refusée\n","operationId":"deleteProjectTag","parameters":[{"name":"projectId","in":"path","description":"ID du projet","required":true,"schema":{"type":"integer","format":"int64"},"example":1},{"name":"tagId","in":"path","description":"ID du tag à supprimer","required":true,"schema":{"type":"integer","format":"int64"},"example":5}],"responses":{"200":{"description":"✅ Tag supprimé avec succès","content":{"application/json":{"example":{"message":"Tag deleted successfully"}}}},"400":{"description":"❌ Tag utilisé par des tickets ou erreur de validation","content":{"application/json":{"example":{"message":"Cannot delete tag: it is used by 5 ticket(s)"}}}}},"security":[{"bearerAuth":[]}]}},"/api/projects/{id}":{"get":{"tags":["🏢 Projects"],"summary":"🔍 Récupérer un projet par ID","description":"Récupère les détails d'un projet spécifique par son identifiant.\n\n### 📊 Données retournées\n- Informations du projet\n- Agents assignés (version simplifiée)\n- Statistiques de base\n","operationId":"getProjectById","parameters":[{"name":"id","in":"path","description":"ID unique du projet","required":true,"schema":{"type":"integer","format":"int64"},"example":1}],"responses":{"200":{"description":"✅ Projet trouvé","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectDTO"},"example":{"id":3,"name":"Application Mobile iOS","description":"Application mobile native pour iOS","isActive":true,"createdAt":"2025-06-25T09:00:00Z","agents":[{"id":2,"username":"pierre.dev","firstName":"Pierre","lastName":"Développeur","roles":["ROLE_DEV"]}],"ticketCount":15,"openTicketsCount":3}}}},"404":{"description":"❌ Projet non trouvé","content":{"application/json":{"example":{"timestamp":"2025-06-25T12:00:00Z","status":404,"error":"Not Found","message":"Ticket avec l'ID 999 introuvable","path":"/api/tickets/999"}}}}},"security":[{"bearerAuth":[]}]},"put":{"tags":["🏢 Projects"],"summary":"✏️ Mettre à jour un projet","description":"Met à jour les informations d'un projet existant.\n\n### 🔐 Permissions\nRéservé aux administrateurs (ADMIN uniquement)\n\n### 📝 Mise à jour\nSeuls les champs fournis sont mis à jour\n","operationId":"updateProject","parameters":[{"name":"id","in":"path","description":"ID du projet à modifier","required":true,"schema":{"type":"integer","format":"int64"},"example":1}],"requestBody":{"description":"Nouvelles données du projet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Project"},"example":{"name":"Application Mobile iOS","description":"Application mobile native pour iOS avec fonctionnalités e-commerce","isActive":true,"clientEmails":["client1@entreprise.com","client2@entreprise.com"]}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"bearerAuth":[]}]},"delete":{"tags":["🏢 Projects"],"summary":"🗑️ Supprimer un projet","description":"Supprime définitivement un projet du système.\n\n### ⚠️ Attention\nCette action est irréversible !\n\n### 🔐 Permissions\nRéservé aux administrateurs (ADMIN uniquement)\n","operationId":"deleteProject","parameters":[{"name":"id","in":"path","description":"ID du projet à supprimer","required":true,"schema":{"type":"integer","format":"int64"},"example":1}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"bearerAuth":[]}]}},"/api/knowledge/articles/{id}":{"get":{"tags":["📚 Base de Connaissances"],"summary":"📖 Détails de l'article","description":"Récupère un article par son ID avec statut de like","operationId":"getArticleById","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}},"put":{"tags":["📚 Base de Connaissances"],"summary":"✏️ Modifier un article","description":"Met à jour un article existant","operationId":"updateArticle","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KnowledgeCreateRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}},"delete":{"tags":["📚 Base de Connaissances"],"summary":"🗑️ Supprimer un article","description":"Supprime un article de la base de connaissances","operationId":"deleteArticle","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/keys/{keyId}":{"put":{"tags":["🔑 API Keys"],"summary":"Mettre à jour une clé API","description":"Modifie les paramètres d'une clé API existante","operationId":"updateApiKey","parameters":[{"name":"keyId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"bearerAuth":[]}]},"delete":{"tags":["🔑 API Keys"],"summary":"Révoquer une clé API","description":"Désactive définitivement une clé API","operationId":"revokeApiKey","parameters":[{"name":"keyId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"bearerAuth":[]}]}},"/api/clients/{id}":{"get":{"tags":["client-controller"],"operationId":"getClientById","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}},"put":{"tags":["client-controller"],"operationId":"updateClient","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}},"delete":{"tags":["client-controller"],"operationId":"deleteClient","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/attachments/{attachmentId}":{"put":{"tags":["📎 Attachments"],"summary":"✏️ Modifier un attachement","description":"Modifie les métadonnées d'un attachement","operationId":"updateAttachment","parameters":[{"name":"attachmentId","in":"path","description":"🆔 ID de l'attachement","required":true,"schema":{"type":"integer","format":"int64"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}},"delete":{"tags":["📎 Attachments"],"summary":"🗑️ Supprimer un attachement","description":"Supprime définitivement un attachement et son fichier","operationId":"deleteAttachment","parameters":[{"name":"attachmentId","in":"path","description":"🆔 ID de l'attachement","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/tickets":{"get":{"tags":["ticket-controller"],"operationId":"getAllTickets","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":100}},{"name":"sortBy","in":"query","required":false,"schema":{"type":"string","default":"id"}},{"name":"sortDir","in":"query","required":false,"schema":{"type":"string","default":"DESC"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PageTicketDTO"}}}}}},"post":{"tags":["ticket-controller"],"operationId":"createTicket","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TicketRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/tickets/{ticketId}/chat":{"get":{"tags":["chat-controller"],"operationId":"getChatMessages","parameters":[{"name":"ticketId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}},"post":{"tags":["chat-controller"],"operationId":"sendChatMessageWithFiles_1","parameters":[{"name":"ticketId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"required":["messageData"],"type":"object","properties":{"messageData":{"type":"string"},"attachments":{"type":"array","items":{"type":"string","format":"binary"}}}}},"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"}}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/tickets/{ticketId}/chat/mark-read":{"post":{"tags":["chat-controller"],"operationId":"markMessagesAsRead","parameters":[{"name":"ticketId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"platformId","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/tickets/{id}/agent-notes":{"get":{"tags":["ticket-controller"],"operationId":"getTicketAgentNotes","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}},"post":{"tags":["ticket-controller"],"operationId":"addAgentNote","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"}}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/tickets/reassign-all":{"post":{"tags":["ticket-controller"],"operationId":"reassignAllOpenTickets","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/test/email":{"post":{"tags":["email-test-controller"],"operationId":"testEmail","parameters":[{"name":"to","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/settings/user/reset/{category}":{"post":{"tags":["settings-controller"],"operationId":"resetUserSettingsToDefault","parameters":[{"name":"category","in":"path","required":true,"schema":{"type":"string","enum":["GENERAL","NOTIFICATIONS","APPEARANCE","SECURITY","SYSTEM","EMAIL","INTEGRATIONS"]}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/settings/user/category/{category}":{"get":{"tags":["settings-controller"],"operationId":"getUserSettingsByCategory","parameters":[{"name":"category","in":"path","required":true,"schema":{"type":"string","enum":["GENERAL","NOTIFICATIONS","APPEARANCE","SECURITY","SYSTEM","EMAIL","INTEGRATIONS"]}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}},"post":{"tags":["settings-controller"],"operationId":"updateUserSettingsByCategory","parameters":[{"name":"category","in":"path","required":true,"schema":{"type":"string","enum":["GENERAL","NOTIFICATIONS","APPEARANCE","SECURITY","SYSTEM","EMAIL","INTEGRATIONS"]}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"}}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/settings/initialize":{"post":{"tags":["settings-controller"],"operationId":"initializeDefaultSettings","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/settings/import":{"post":{"tags":["settings-controller"],"operationId":"importSettings","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsDTO"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/settings/global/reset/{category}":{"post":{"tags":["settings-controller"],"operationId":"resetGlobalSettingsToDefault","parameters":[{"name":"category","in":"path","required":true,"schema":{"type":"string","enum":["GENERAL","NOTIFICATIONS","APPEARANCE","SECURITY","SYSTEM","EMAIL","INTEGRATIONS"]}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/settings/global/category/{category}":{"get":{"tags":["settings-controller"],"operationId":"getGlobalSettingsByCategory","parameters":[{"name":"category","in":"path","required":true,"schema":{"type":"string","enum":["GENERAL","NOTIFICATIONS","APPEARANCE","SECURITY","SYSTEM","EMAIL","INTEGRATIONS"]}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}},"post":{"tags":["settings-controller"],"operationId":"updateGlobalSettingsByCategory","parameters":[{"name":"category","in":"path","required":true,"schema":{"type":"string","enum":["GENERAL","NOTIFICATIONS","APPEARANCE","SECURITY","SYSTEM","EMAIL","INTEGRATIONS"]}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"}}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/projects":{"get":{"tags":["🏢 Projects"],"summary":"📋 Récupérer tous les projets","description":"Récupère la liste complète de tous les projets du système.\n\n### 🔐 Permissions requises\n- **ADMIN** : Accès complet\n- **DEV, OPERATIONS, SECURITY, SALES** : Lecture seule\n\n### 📊 Retour\nListe des projets avec leurs informations de base (sans relations)\n","operationId":"getAllProjects","responses":{"401":{"description":"❌ Token manquant ou invalide","content":{"application/json":{"example":{"timestamp":"2025-06-25T12:00:00Z","status":401,"error":"Unauthorized","message":"Token JWT expiré ou invalide","path":"/api/tickets"}}}},"200":{"description":"✅ Liste des projets récupérée avec succès","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectDTO"},"examples":{"Succès - Liste des projets":{"description":"Succès - Liste des projets","value":{"id":3,"name":"Application Mobile iOS","description":"Application mobile native pour iOS","isActive":true,"createdAt":"2025-06-25T09:00:00Z","agents":[{"id":2,"username":"pierre.dev","firstName":"Pierre","lastName":"Développeur","roles":["ROLE_DEV"]}],"ticketCount":15,"openTicketsCount":3}}}}}},"403":{"description":"❌ Permissions insuffisantes","content":{"application/json":{"example":{"timestamp":"2025-06-25T12:00:00Z","status":403,"error":"Forbidden","message":"Accès refusé : permissions insuffisantes","path":"/api/users"}}}},"500":{"description":"❌ Erreur serveur","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProjectDTO"}}}}}},"security":[{"bearerAuth":[]}]},"post":{"tags":["🏢 Projects"],"summary":"➕ Créer un nouveau projet","description":"Crée un nouveau projet dans le système.\n\n### 🔐 Permissions\nRéservé aux administrateurs (ADMIN uniquement)\n\n### ✅ Champs requis\n- **name** : Nom du projet\n- **description** : Description détaillée\n\n### 📝 Champs optionnels\n- **isActive** : Statut actif (défaut: true)\n- **clientEmails** : Liste des emails clients\n","operationId":"createProject","requestBody":{"description":"Données du nouveau projet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Project"},"examples":{"Nouveau projet":{"description":"Nouveau projet","value":{"name":"Application Mobile iOS","description":"Application mobile native pour iOS avec fonctionnalités e-commerce","isActive":true,"clientEmails":["client1@entreprise.com","client2@entreprise.com"]}}}}},"required":true},"responses":{"200":{"description":"✅ Projet créé avec succès","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectDTO"},"example":{"id":3,"name":"Application Mobile iOS","description":"Application mobile native pour iOS","isActive":true,"createdAt":"2025-06-25T09:00:00Z","agents":[{"id":2,"username":"pierre.dev","firstName":"Pierre","lastName":"Développeur","roles":["ROLE_DEV"]}],"ticketCount":15,"openTicketsCount":3}}}},"400":{"description":"❌ Données invalides","content":{"application/json":{"example":{"timestamp":"2025-06-25T12:00:00Z","status":400,"error":"Bad Request","message":"Erreurs de validation","validationErrors":{"title":"Le titre est obligatoire","description":"La description doit faire au moins 10 caractères","priority":"Priorité invalide (LOW, MEDIUM, HIGH, URGENT)"}}}}}},"security":[{"bearerAuth":[]}]}},"/api/projects/{projectId}/tags":{"get":{"tags":["🏷️ Project Tags"],"summary":"📋 Récupérer les tags d'un projet","description":"Récupère tous les tags associés à un projet spécifique.\n\n### 🏷️ Utilisation\nLes tags permettent de catégoriser et filtrer les tickets d'un projet\n\n### 📊 Retour\nListe des tags avec leurs informations (nom, couleur, statistiques d'usage)\n","operationId":"getProjectTags","parameters":[{"name":"projectId","in":"path","description":"ID unique du projet","required":true,"schema":{"type":"integer","format":"int64"},"example":1}],"responses":{"404":{"description":"❌ Projet non trouvé","content":{"application/json":{"example":{"timestamp":"2025-06-25T12:00:00Z","status":404,"error":"Not Found","message":"Ticket avec l'ID 999 introuvable","path":"/api/tickets/999"}}}},"200":{"description":"✅ Tags récupérés avec succès","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Tag"},"examples":{"Liste des tags":{"description":"Liste des tags","value":[{"id":1,"name":"database","color":"#FF6B6B","project":{"id":1,"code":"WEB","name":"Site Web E-commerce"}},{"id":2,"name":"mysql","color":"#4ECDC4","project":{"id":1,"code":"WEB","name":"Site Web E-commerce"}}]}}}}},"500":{"description":"❌ Erreur serveur","content":{"application/json":{"example":{"timestamp":"2025-06-27T12:00:00Z","status":500,"error":"Internal Server Error","message":"Error retrieving project tags","path":"/api/projects/1/tags"}}}}},"security":[{"bearerAuth":[]}]},"post":{"tags":["🏷️ Project Tags"],"summary":"➕ Créer un nouveau tag","description":"Crée un nouveau tag pour un projet spécifique.\n\n### 🔐 Permissions\nRéservé aux administrateurs (ADMIN uniquement)\n\n### ✅ Règles de validation\n- Le nom du tag est obligatoire\n- Le nom est normalisé (minuscules, espaces supprimés)\n- Pas de doublons par projet\n\n### 🎨 Couleur automatique\nSi aucune couleur n'est fournie, une couleur est assignée automatiquement\n","operationId":"createProjectTag","parameters":[{"name":"projectId","in":"path","description":"ID du projet","required":true,"schema":{"type":"integer","format":"int64"},"example":1}],"requestBody":{"description":"Données du nouveau tag","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"}},"examples":{"Nouveau tag":{"description":"Nouveau tag","value":{"name":"performance","color":"#9B59B6"}}}}},"required":true},"responses":{"200":{"description":"✅ Tag créé avec succès","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Tag"},"examples":{"Tag créé":{"description":"Tag créé","value":{"id":15,"name":"performance","color":"#9B59B6","project":{"id":1,"code":"WEB","name":"Site Web E-commerce"},"createdAt":"2025-06-27T14:30:00Z"}}}}}},"400":{"description":"❌ Données invalides ou tag déjà existant","content":{"application/json":{"examples":{"Tag déjà existant":{"description":"Tag déjà existant","value":{"message":"Tag 'database' already exists for this project"}}}}}}},"security":[{"bearerAuth":[]}]}},"/api/projects/{projectId}/agents":{"get":{"tags":["🏢 Projects"],"summary":"👥 Agents du projet","description":"Récupère la liste de tous les agents assignés à un projet","operationId":"getProjectAgents","parameters":[{"name":"projectId","in":"path","description":"ID du projet","required":true,"schema":{"type":"integer","format":"int64"},"example":1}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"bearerAuth":[]}]},"post":{"tags":["🏢 Projects"],"summary":"👥 Assigner plusieurs agents","description":"Assigne plusieurs agents à un projet en une seule opération.\n\n### 📋 Corps de requête\n```json\n{\n  \"agentIds\": [1, 2, 3, 4]\n}\n```\n\n### 📊 Réponse\n- **200** : Tous les agents assignés\n- **207** : Certains agents assignés, d'autres échoués\n","operationId":"assignMultipleAgentsToProject","parameters":[{"name":"projectId","in":"path","description":"ID du projet","required":true,"schema":{"type":"integer","format":"int64"},"example":1}],"requestBody":{"description":"Liste des IDs d'agents à assigner","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"array","items":{"type":"integer","format":"int64"}}},"example":{"agentIds":[1,2,3,4,5]}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"bearerAuth":[]}]}},"/api/projects/{projectId}/agents/{agentId}":{"post":{"tags":["🏢 Projects"],"summary":"👤 Assigner un agent au projet","description":"Assigne un agent spécifique à un projet.\n\n### 🔐 Permissions\nRéservé aux administrateurs (ADMIN uniquement)\n\n### 💡 Fonctionnement\n- L'agent est ajouté à la liste des agents du projet\n- Permet l'affectation automatique des tickets\n","operationId":"assignAgentToProject","parameters":[{"name":"projectId","in":"path","description":"ID du projet","required":true,"schema":{"type":"integer","format":"int64"},"example":1},{"name":"agentId","in":"path","description":"ID de l'agent à assigner","required":true,"schema":{"type":"integer","format":"int64"},"example":5}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"bearerAuth":[]}]},"delete":{"tags":["🏢 Projects"],"summary":"🗑️ Retirer un agent du projet","description":"Retire un agent spécifique d'un projet","operationId":"removeAgentFromProject","parameters":[{"name":"projectId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"agentId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"bearerAuth":[]}]}},"/api/platforms/tickets":{"get":{"tags":["🌐 Platform API"],"summary":"Lister les tickets de la plateforme","description":"Liste les tickets avec filtres optionnels par email client, statut et priorité","operationId":"getTickets","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":10}},{"name":"sortBy","in":"query","required":false,"schema":{"type":"string","default":"createdAt"}},{"name":"sortDir","in":"query","required":false,"schema":{"type":"string","default":"DESC"}},{"name":"clientEmail","in":"query","required":false,"schema":{"type":"string"}},{"name":"status","in":"query","required":false,"schema":{"type":"string"}},{"name":"priority","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"apiKey":[]}]},"post":{"tags":["🌐 Platform API"],"summary":"Créer un ticket depuis une plateforme","description":"Crée un nouveau ticket dans le projet associé à la clé API","operationId":"createTicket_1","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlatformTicketRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"apiKey":[]}]}},"/api/platforms/tickets/{id}/messages":{"get":{"tags":["🌐 Platform API"],"summary":"Récupérer les messages d'un ticket","operationId":"getMessages","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"apiKey":[]}]},"post":{"tags":["🌐 Platform API"],"summary":"Ajouter un message à un ticket","description":"Ajoute un message à un ticket avec support des fichiers joints.\n\n**Formats supportés:** PDF, Images (JPG, PNG), Documents (DOC, DOCX, XLS, XLSX)\n**Taille max par fichier:** 10 MB\n","operationId":"addMessage","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"content","in":"query","required":true,"schema":{"type":"string"}},{"name":"senderName","in":"query","required":false,"schema":{"type":"string"}},{"name":"senderEmail","in":"query","required":false,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"attachments":{"type":"array","items":{"type":"string","format":"binary"}}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"apiKey":[]}]}},"/api/notifications":{"get":{"tags":["notification-controller"],"operationId":"getUserNotifications","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/NotificationDTO"}}}}}}},"post":{"tags":["notification-controller"],"operationId":"createNotification","parameters":[{"name":"userId","in":"query","required":true,"schema":{"type":"integer","format":"int64"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateNotificationDTO"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationDTO"}}}}}}},"/api/knowledge/smart-search":{"post":{"tags":["📚 Base de Connaissances"],"summary":"🔍 Recherche intelligente","description":"Recherche d'articles basée sur le titre et la description d'un ticket","operationId":"smartSearch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmartSearchRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/KnowledgeArticleDTO"}}}}}}}},"/api/knowledge/likes/sync":{"post":{"tags":["📚 Base de Connaissances"],"summary":"🔄 Synchroniser les compteurs","description":"Synchronise les compteurs de likes (admin uniquement)","operationId":"syncLikeCounts","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/knowledge/articles":{"get":{"tags":["📚 Base de Connaissances"],"summary":"📚 Tous les articles","description":"Récupère tous les articles de la base de connaissances avec pagination","operationId":"getAllArticles","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20}},{"name":"sortBy","in":"query","required":false,"schema":{"type":"string","default":"updatedAt"}},{"name":"sortDir","in":"query","required":false,"schema":{"type":"string","default":"DESC"}},{"name":"projectId","in":"query","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PageKnowledgeArticleDTO"}}}}}},"post":{"tags":["📚 Base de Connaissances"],"summary":"➕ Créer un article","description":"Crée un nouvel article de connaissances","operationId":"createArticle","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KnowledgeCreateRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/knowledge/articles/{id}/view":{"post":{"tags":["📚 Base de Connaissances"],"summary":"👁️ Incrémenter les vues","description":"Incrémente le compteur de vues d'un article","operationId":"incrementViewCount","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK"}}}},"/api/knowledge/articles/{id}/helpful":{"post":{"tags":["📚 Base de Connaissances"],"summary":"👍 Marquer comme utile","description":"Marque un article comme utile","operationId":"markAsHelpful","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK"}}}},"/api/knowledge/articles/{articleId}/like":{"post":{"tags":["📚 Base de Connaissances"],"summary":"👍 Liker/Unliker un article","description":"Like ou unlike un article avec gestion des doublons","operationId":"toggleLike","parameters":[{"name":"articleId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}},"delete":{"tags":["📚 Base de Connaissances"],"summary":"💔 Retirer son like","description":"Retire le like de l'utilisateur actuel","operationId":"unlikeArticle","parameters":[{"name":"articleId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/knowledge/articles/{articleId}/like-only":{"post":{"tags":["📚 Base de Connaissances"],"summary":"👍 Liker un article","description":"Like un article (erreur si déjà liké)","operationId":"likeArticle","parameters":[{"name":"articleId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/knowledge/articles/{articleId}/attachments":{"get":{"tags":["📚 Base de Connaissances"],"summary":"📋 Fichiers de l'article","description":"Récupère tous les fichiers attachés à un article","operationId":"getArticleAttachments","parameters":[{"name":"articleId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"publicOnly","in":"query","required":false,"schema":{"type":"boolean","default":false}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}},"post":{"tags":["📚 Base de Connaissances"],"summary":"📎 Ajouter des fichiers","description":"Ajoute des fichiers à un article de connaissances","operationId":"uploadAttachments","parameters":[{"name":"articleId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"description","in":"query","required":false,"schema":{"type":"string"}},{"name":"isPublic","in":"query","required":false,"schema":{"type":"boolean","default":true}}],"requestBody":{"content":{"application/json":{"schema":{"required":["files"],"type":"object","properties":{"files":{"type":"array","items":{"type":"string","format":"binary"}}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/keys":{"get":{"tags":["🔑 API Keys"],"summary":"Lister mes clés API","description":"Récupère toutes les clés API de l'utilisateur connecté","operationId":"getMyApiKeys","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":10}},{"name":"sortBy","in":"query","required":false,"schema":{"type":"string","default":"createdAt"}},{"name":"sortDir","in":"query","required":false,"schema":{"type":"string","default":"DESC"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"bearerAuth":[]}]},"post":{"tags":["🔑 API Keys"],"summary":"Créer une nouvelle clé API","description":"Génère une nouvelle clé API avec les permissions spécifiées.\n\n**Permissions disponibles :**\n- READ_TICKETS, READ_USERS, READ_PROJECTS, READ_STATS\n- WRITE_TICKETS, WRITE_USERS, WRITE_PROJECTS\n- ADMIN_ACCESS, EXTERNAL_API, DELETE_OPERATIONS\n- SEND_NOTIFICATIONS, ACCESS_INTERNAL_NOTES\n","operationId":"createApiKey","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"bearerAuth":[]}]}},"/api/keys/{keyId}/reveal":{"post":{"tags":["🔑 API Keys"],"summary":"Révéler la valeur d'une clé API","description":"Révèle la valeur complète d'une clé API avec vérification du mot de passe","operationId":"revealApiKey","parameters":[{"name":"keyId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"}}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"bearerAuth":[]}]}},"/api/keys/{keyId}/regenerate":{"post":{"tags":["🔑 API Keys"],"summary":"Régénérer une clé API","description":"Génère une nouvelle valeur pour une clé API existante","operationId":"regenerateApiKey","parameters":[{"name":"keyId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"}}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"bearerAuth":[]}]}},"/api/external/tickets/{ticketId}/client-notes":{"post":{"tags":["🏪 External API","� External API"],"summary":"📝 Ajouter une note client à un ticket","description":"## Ajouter une note personnelle à un ticket\n\n### 🔐 Sécurité\n- Le ticket doit appartenir au client identifié par le token\n- Seules les notes clients sont autorisées (pas de messages système)\n\n### 📝 Fonctionnalités\n- Ajout de notes personnelles au ticket\n- Historique des notes conservé\n- Notification automatique des agents\n- Limitation de taille pour éviter les abus\n\n### 💡 Cas d'usage\n- Précisions supplémentaires sur le problème\n- Mises à jour du client sur l'évolution\n- Informations complémentaires\n- Feedback client\n","operationId":"addClientNoteToTicket","parameters":[{"name":"ticketId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"X-Marketplace-Token","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-Platform-ID","in":"header","required":false,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/external/tickets/create-and-retrieve":{"post":{"tags":["🏪 External API","� External API"],"summary":"🎫 Créer un ticket depuis la marketplace","description":"## Créer un nouveau ticket de support\n\n### 🔄 Fonctionnement\n1. **Validation** du token marketplace\n2. **Détection automatique** du projet basée sur le contenu\n3. **Gestion automatique** du client (création si inexistant)\n4. **Création** du ticket avec assignation automatique\n5. **Upload des fichiers attachés** (optionnel)\n6. **Retour** des informations complètes du ticket créé\n\n### 🎯 Détection de Projet\nLe projet est automatiquement détecté en analysant les tags fournis.\nLe système recherche les correspondances avec les tags existants de chaque projet\net les mots-clés spécifiques. Si aucun tag n'est fourni, la détection se base\nsur le titre et la description.\n\n### 👥 Gestion Client\nLe client est automatiquement créé ou mis à jour basé sur l'email du token.\nLes informations client dans la requête sont optionnelles mais recommandées.\n\n### 📎 Fichiers Attachés\nSupport complet des fichiers attachés avec :\n- Images (JPG, PNG, GIF, WebP)\n- Documents (PDF, Word, Excel)\n- Archives (ZIP)\n- Taille max : 10MB par fichier\n- Maximum 5 fichiers par ticket\n\n### 📝 Notes du Client\nLes clients peuvent maintenant ajouter des notes personnelles à leurs tickets\npour fournir du contexte supplémentaire.\n","operationId":"createAndRetrieveTicket","parameters":[{"name":"X-Marketplace-Token","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-Platform-ID","in":"header","required":false,"schema":{"type":"string"}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"required":["ticketData"],"type":"object","properties":{"ticketData":{"type":"string"},"attachments":{"type":"array","items":{"type":"string","format":"binary"}}}}}}},"responses":{"500":{"description":"💥 Erreur serveur","content":{"application/json":{"examples":{"Erreur serveur":{"description":"Erreur serveur","value":{"message":"Internal server error: Database connection failed"}}}}}},"400":{"description":"❌ Données invalides","content":{"application/json":{"examples":{"Erreur validation":{"description":"Erreur validation","value":{"message":"Title is required"}}}}}},"201":{"description":"✅ Ticket créé avec succès","content":{"application/json":{"examples":{"Ticket créé avec attachements":{"description":"Ticket créé avec attachements","value":{"ticket":{"id":123,"title":"Problème de connexion","description":"Impossible de se connecter...","status":"OPEN","priority":"MEDIUM","createdAt":"2025-01-15T10:30:00Z","sourceType":"MARKETPLACE","sourceReference":"platform-123"},"client":{"id":45,"email":"client@example.com","firstName":"Jean","lastName":"Dupont","company":"Entreprise SARL"},"project":{"id":1,"code":"WEB","name":"Site Web Corporate"},"attachments":[{"id":789,"originalFilename":"screenshot.png","fileSize":2048576,"fileSizeFormatted":"2.0 MB","contentType":"image/png","isImage":true,"downloadUrl":"/api/attachments/ticket_123_1704448200000_screenshot.png/download","previewUrl":"/api/attachments/ticket_123_1704448200000_screenshot.png/preview","uploadedAt":"2025-01-15T10:30:00Z"}],"attachmentCount":1,"projectDetection":{"detectedFromTags":true,"detectedProjectCode":"WEB","detectedProjectName":"Site Web Corporate","providedTags":["website","css","javascript"],"matchedKeywords":{"website":"Site web","css":"CSS"}},"success":true,"message":"Ticket créé avec succès"}}}}}},"401":{"description":"🔒 Token marketplace invalide","content":{"application/json":{"examples":{"Token invalide":{"description":"Token invalide","value":{"message":"Invalid marketplace token"}}}}}}}}},"/api/external/projects/detect":{"post":{"tags":["� External API"],"summary":"🤖 Détecter automatiquement un projet","description":"## Détection automatique de projet\n\n### 🔍 Analyse de contenu\nLe système analyse le titre et la description pour détecter\nautomatiquement le projet le plus approprié basé sur :\n- **Mots-clés spécifiques** par projet\n- **Contexte technique** mentionné\n- **Type de problème** décrit\n\n### 📊 Informations retournées\n- Projet détecté avec ses détails\n- Mots-clés qui ont permis la détection\n- Liste complète des mots-clés disponibles\n- Score de confiance de la détection\n\n### 💡 Utilisation\n- Test avant création de ticket\n- Validation de la logique de détection\n- Debug des règles de matching\n","operationId":"detectProject","parameters":[{"name":"X-Marketplace-Token","in":"header","description":"🔑 Token marketplace (Base64 JSON avec email client)","required":true,"schema":{"type":"string"},"example":"eyJlbWFpbCI6ImNsaWVudEBleGFtcGxlLmNvbSJ9"},{"name":"X-Platform-ID","in":"header","description":"🏷️ Identifiant de la plateforme marketplace","required":false,"schema":{"type":"string"},"example":"shopify-store-123"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"},"description":"📝 Contenu à analyser pour la détection"}}},"required":true},"responses":{"401":{"description":"🔒 Token invalide","content":{"application/json":{"examples":{"Token invalide":{"description":"Token invalide","value":{"message":"Invalid marketplace token"}}}}}},"200":{"description":"✅ Détection effectuée","content":{"application/json":{"examples":{"Projet détecté":{"description":"Projet détecté","value":{"detectedProject":{"id":1,"code":"WEB","name":"Site Web Corporate"},"matchedKeywords":{"site":"Site web","connexion":"Authentification","mysql":"Base de données"},"allAvailableKeywords":{"site":"Site web","web":"Développement web","css":"Styles CSS","javascript":"Scripts JS"}}}}}}},"400":{"description":"❌ Contenu manquant","content":{"application/json":{"examples":{"Contenu requis":{"description":"Contenu requis","value":{"message":"Either title or description must be provided"}}}}}}}}},"/api/external/chat/tickets/{ticketId}/messages":{"get":{"tags":["🗨️ External Chat API"],"summary":"📖 Récupérer les messages de chat","description":"Récupère l'historique des messages de chat pour un ticket avec pagination.\n\n⚠️ IMPORTANT : Cet endpoint récupère UNIQUEMENT les messages de chat bidirectionnel :\n- Messages des agents internes (AGENT_INTERNAL)\n- Messages clients de chat actif (CLIENT_EXTERNAL avec sessionId)\n- Messages système (SYSTEM)\n\n❌ Cet endpoint EXCLUT :\n- Notes clients externes (formulaires web, sans session)\n- Notes privées des agents\n- Messages avec platformId=web_form ou note_form\n\n### 🔍 Fonctionnalités\n- Pagination des messages de chat uniquement\n- Filtrage par plateforme\n- Statut de lecture\n- Messages temps réel\n","operationId":"getChatMessages_1","parameters":[{"name":"ticketId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"X-Marketplace-Token","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-Platform-ID","in":"header","required":false,"schema":{"type":"string"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20}},{"name":"since","in":"query","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}},"post":{"tags":["🗨️ External Chat API"],"summary":"💬 Envoyer un message de chat","description":"Permet à une plateforme externe d'envoyer un message de chat pour un ticket.\nCe système remplace l'envoi d'emails par une discussion en temps réel.\n\n### 🚀 Fonctionnalités\n- Messages instantanés sans email\n- Suivi en temps réel de la conversation\n- Notification automatique des agents\n- Statut de lecture des messages\n","operationId":"sendChatMessage","parameters":[{"name":"ticketId","in":"path","description":"🎫 ID du ticket","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"X-Marketplace-Token","in":"header","description":"🔑 Token marketplace","required":true,"schema":{"type":"string"}},{"name":"X-Platform-ID","in":"header","description":"🏷️ ID de la plateforme","required":false,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"object"},"description":"💬 Contenu du message de chat"}}},"required":true},"responses":{"400":{"description":"❌ Données invalides","content":{"application/json":{"schema":{"type":"object"}}}},"404":{"description":"🔍 Ticket non trouvé","content":{"application/json":{"schema":{"type":"object"}}}},"403":{"description":"🚫 Accès refusé","content":{"application/json":{"schema":{"type":"object"}}}},"201":{"description":"✅ Message envoyé avec succès","content":{"application/json":{"examples":{"Message envoyé":{"description":"Message envoyé","value":{"success":true,"message":"Chat message sent successfully","messageId":789,"ticket":{"id":123,"title":"Problème de connexion","status":"IN_PROGRESS"},"chatMessage":{"id":789,"content":"Merci pour votre réponse, j'ai encore une question...","senderName":"Jean Dupont","createdAt":"2025-06-30T14:30:00Z","isFromExternal":true}}}}}}}}}},"/api/external/chat/tickets/{ticketId}/mark-read":{"post":{"tags":["🗨️ External Chat API"],"summary":"✅ Marquer les messages comme lus","description":"Marque tous les messages non lus comme lus pour l'utilisateur externe.","operationId":"markMessagesAsRead_1","parameters":[{"name":"ticketId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"X-Marketplace-Token","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-Platform-ID","in":"header","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/clients":{"get":{"tags":["client-controller"],"operationId":"getAllClients","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}},"post":{"tags":["client-controller"],"operationId":"createClient","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/clients/{id}/services":{"post":{"tags":["client-controller"],"operationId":"addClientService","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"}}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/auth/test-email-config":{"post":{"tags":["🔐 Authentication"],"summary":"📧 Tester la configuration email","description":"Teste l'envoi d'email pour vérifier la configuration (Admin uniquement)","operationId":"testEmailConfiguration","parameters":[{"name":"testEmail","in":"query","description":"Email de destination pour le test","required":true,"schema":{"type":"string"},"example":"test@example.com"}],"responses":{"403":{"description":"🚫 Accès refusé - Admin requis","content":{"application/json":{"schema":{"type":"object"}}}},"200":{"description":"✅ Email de test envoyé","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"❌ Erreur de configuration email","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"bearerAuth":[]}]}},"/api/auth/reset-password":{"post":{"tags":["🔐 Authentication"],"summary":"🔄 Réinitialiser le mot de passe","description":"### Réinitialisation effective du mot de passe\n\n**Processus :**\n1. Validation du token\n2. Vérification de la concordance des mots de passe\n3. Mise à jour sécurisée du mot de passe\n4. Invalidation du token\n5. Envoi d'un email de confirmation\n\n**Exigences mot de passe :**\n- Minimum 6 caractères\n- Confirmation obligatoire\n","operationId":"resetPassword","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetPasswordRequest"}}},"required":true},"responses":{"200":{"description":"✅ Mot de passe réinitialisé avec succès","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"❌ Erreur de validation ou token invalide","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/auth/register":{"post":{"tags":["🔐 Authentication"],"summary":"👤 Inscription d'un nouvel utilisateur avec photo","description":"### Création d'un nouveau compte utilisateur avec photo de profil\n\n**🔒 Accès :** Administrateurs uniquement\n\n**Fonctionnalités :**\n- Validation automatique des données\n- Vérification d'unicité (email, username)\n- Hashage sécurisé du mot de passe\n- Attribution de rôles\n- **📸 Upload de photo de profil (optionnel)**\n- **📧 Envoi automatique des identifiants par email**\n\n**Formats d'image acceptés :** JPEG, PNG, GIF, WebP\n**Taille maximale :** 5MB\n\n**Rôles disponibles :**\n- `ROLE_ADMIN` : Administration complète\n- `ROLE_DEV` : Développement et tickets techniques\n- `ROLE_OPERATIONS` : Infrastructure et opérations\n- `ROLE_SECURITY` : Sécurité et protection\n- `ROLE_SALES` : Commercial et facturation\n- `ROLE_CLIENT` : Client (rôle par défaut)\n","operationId":"registerUser","requestBody":{"content":{"multipart/form-data":{"schema":{"required":["userData"],"type":"object","properties":{"userData":{"type":"string","description":"Données du nouvel utilisateur (JSON)"},"profilePicture":{"type":"string","description":"Photo de profil (optionnelle)","format":"binary"}}}}}},"responses":{"400":{"description":"❌ Erreur de validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"200":{"description":"✅ Utilisateur créé avec succès et email envoyé","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"403":{"description":"🚫 Accès refusé - Admin requis","content":{"application/json":{}}}},"security":[{"bearerAuth":[]}]}},"/api/auth/logout":{"post":{"tags":["🔐 Authentication"],"summary":"🚪 Déconnexion utilisateur","description":"### Déconnexion sécurisée\n\n**Actions effectuées :**\n- Nettoyage du contexte de sécurité\n- Invalidation de la session locale\n- Log de déconnexion pour audit\n\n**Note :** Le token JWT reste valide jusqu'à expiration.\nPour une sécurité maximale, implémentez une blacklist côté client.\n","operationId":"logoutUser","responses":{"200":{"description":"✅ Déconnexion réussie","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"},"examples":{"Déconnexion réussie":{"description":"Déconnexion réussie","value":{"message":"User logged out successfully!"}}}}}}},"security":[{"bearerAuth":[]}]}},"/api/auth/login":{"post":{"tags":["🔐 Authentication"],"summary":"🔑 Connexion utilisateur","description":"### Authentification avec email et mot de passe\n\nRetourne un token JWT à utiliser dans les prochaines requêtes.\n\n**Processus :**\n1. Validation des identifiants\n2. Génération du token JWT\n3. Retour des informations utilisateur + token\n\n**Utilisation du token :**\n```\nAuthorization: Bearer <token>\n```\n\n⚠️ **Important :** Le token expire après 24h\n","operationId":"authenticateUser","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}},"required":true},"responses":{"200":{"description":"✅ Connexion réussie","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JwtResponse"},"examples":{"Connexion réussie":{"description":"Connexion réussie","value":{"token":"eyJhbGciOiJIUzI1NiJ9...","type":"Bearer","id":1,"username":"admin","email":"admin@systalink.fr","firstName":"Admin","lastName":"Système","phone":"+33123456789","company":"Systalink","roles":["ROLE_ADMIN"]}}}}}},"400":{"description":"❌ Identifiants invalides","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"},"examples":{"Erreur authentification":{"description":"Erreur authentification","value":{"message":"Authentication failed: Bad credentials"}}}}}}}}},"/api/auth/forgot-password":{"post":{"tags":["🔐 Authentication"],"summary":"🔑 Mot de passe oublié","description":"### Demande de réinitialisation de mot de passe\n\n**Processus :**\n1. Validation de l'email\n2. Génération d'un token sécurisé (valide 24h)\n3. Envoi d'un email avec le lien de réinitialisation\n\n**Sécurité :**\n- Un seul token valide par utilisateur\n- Expiration automatique après 24h\n- Email de confirmation après changement\n\n⚠️ **Note :** Pour la sécurité, la réponse sera toujours positive même si l'email n'existe pas.\n","operationId":"forgotPassword","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForgotPasswordRequest"}}},"required":true},"responses":{"429":{"description":"⏰ Trop de tentatives","content":{"application/json":{"schema":{"type":"object"}}}},"200":{"description":"✅ Email de réinitialisation envoyé","content":{"application/json":{"example":{"message":"Si cet email existe dans notre système, vous recevrez un lien de réinitialisation."}}}},"400":{"description":"❌ Email invalide","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/auth/force-password-reset":{"post":{"tags":["🔐 Authentication"],"summary":"🔄 Forcer une réinitialisation","description":"Force une réinitialisation de mot de passe en nettoyant les anciens tokens (Admin uniquement)","operationId":"forcePasswordReset","parameters":[{"name":"email","in":"query","description":"Email pour lequel forcer la réinitialisation","required":true,"schema":{"type":"string"},"example":"user@example.com"}],"responses":{"200":{"description":"✅ Réinitialisation forcée","content":{"application/json":{"schema":{"type":"object"}}}},"403":{"description":"🚫 Accès refusé - Admin requis","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"bearerAuth":[]}]}},"/api/auth/cleanup-expired-tokens":{"post":{"tags":["🔐 Authentication"],"summary":"🧹 Nettoyer les tokens expirés","description":"Force le nettoyage des tokens de réinitialisation expirés (Admin uniquement)","operationId":"cleanupExpiredTokens","responses":{"200":{"description":"✅ Tokens nettoyés avec succès","content":{"application/json":{"schema":{"type":"object"}}}},"403":{"description":"🚫 Accès refusé - Admin requis","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"bearerAuth":[]}]}},"/api/attachments/upload":{"post":{"tags":["📎 Attachments"],"summary":"📤 Upload de fichiers","description":"Upload de fichiers pour n'importe quelle entité du système.\n\n### Types d'entités supportés :\n- TICKET : Fichiers joints à un ticket\n- CHAT_MESSAGE : Fichiers dans les messages de chat\n- PROJECT : Documents de projet\n- USER : Avatar ou documents utilisateur\n\n### Limitations :\n- Taille maximale par fichier : 10MB\n- Nombre maximum de fichiers : 10\n- Types autorisés : images, PDF, documents Office\n","operationId":"uploadFiles","parameters":[{"name":"entityType","in":"query","description":"🏷️ Type d'entité","required":true,"schema":{"type":"string"}},{"name":"entityId","in":"query","description":"🆔 ID de l'entité","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"description","in":"query","description":"📝 Description optionnelle","required":false,"schema":{"type":"string"}},{"name":"isPublic","in":"query","description":"🌐 Fichiers publics","required":false,"schema":{"type":"boolean","default":true}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"required":["files"],"type":"object","properties":{"files":{"type":"array","description":"📁 Fichiers à uploader","items":{"type":"string","format":"binary"}}}}}}},"responses":{"401":{"description":"🔒 Non autorisé","content":{"application/json":{"schema":{"type":"object"}}}},"201":{"description":"✅ Fichiers uploadés avec succès","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"❌ Validation échouée","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/tickets/{id}/status":{"patch":{"tags":["ticket-controller"],"operationId":"updateTicketStatus","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"}}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/tickets/{id}/project":{"patch":{"tags":["ticket-controller"],"operationId":"assignTicketToProject","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"integer","format":"int64"}}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/tickets/{id}/assign":{"patch":{"tags":["ticket-controller"],"operationId":"assignTicket","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"integer","format":"int64"}}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/notifications/{id}/unread":{"patch":{"tags":["notification-controller"],"operationId":"markAsUnread","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}}}}},"/api/notifications/{id}/read":{"patch":{"tags":["notification-controller"],"operationId":"markAsRead","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}}}}},"/api/notifications/mark-all-read":{"patch":{"tags":["notification-controller"],"operationId":"markAllAsRead","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}}}}},"/api/users":{"get":{"tags":["👥 Users"],"summary":"📋 Liste des utilisateurs","description":"Récupère la liste complète des utilisateurs (Admin uniquement)","operationId":"getAllUsers","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/User"}}}}}}}},"/api/users/me":{"get":{"tags":["👥 Users"],"summary":"👤 Informations utilisateur connecté","description":"Récupère les informations de l'utilisateur actuellement connecté","operationId":"getCurrentUser","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/tickets/{ticketId}/chat/unread-count":{"get":{"tags":["chat-controller"],"operationId":"getUnreadCount","parameters":[{"name":"ticketId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"platformId","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/tickets/with-message-count":{"get":{"tags":["ticket-controller"],"operationId":"getAllTicketsWithMessageCount","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":10}},{"name":"sortBy","in":"query","required":false,"schema":{"type":"string","default":"id"}},{"name":"sortDir","in":"query","required":false,"schema":{"type":"string","default":"DESC"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PageTicketDTO"}}}}}}},"/api/tickets/status/{status}":{"get":{"tags":["ticket-controller"],"operationId":"getTicketsByStatus","parameters":[{"name":"status","in":"path","required":true,"schema":{"type":"string"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":10}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PageTicket"}}}}}}},"/api/tickets/stats":{"get":{"tags":["ticket-controller"],"operationId":"getTicketStats","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TicketStatsResponse"}}}}}}},"/api/tickets/project/{projectId}":{"get":{"tags":["ticket-controller"],"operationId":"getTicketsByProject","parameters":[{"name":"projectId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":10}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PageTicket"}}}}}}},"/api/tickets/project/{projectId}/unassigned":{"get":{"tags":["ticket-controller"],"operationId":"getUnassignedProjectTickets","parameters":[{"name":"projectId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":10}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/tickets/project/{projectId}/status/{status}":{"get":{"tags":["ticket-controller"],"operationId":"getProjectTicketsByStatus","parameters":[{"name":"projectId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"status","in":"path","required":true,"schema":{"type":"string"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":10}},{"name":"sortBy","in":"query","required":false,"schema":{"type":"string","default":"updatedAt"}},{"name":"sortDir","in":"query","required":false,"schema":{"type":"string","default":"DESC"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/tickets/project/{projectId}/stats":{"get":{"tags":["ticket-controller"],"operationId":"getProjectTicketStats","parameters":[{"name":"projectId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/tickets/project/{projectId}/recent":{"get":{"tags":["ticket-controller"],"operationId":"getRecentProjectTickets","parameters":[{"name":"projectId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":7}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/tickets/project/{projectId}/export":{"get":{"tags":["ticket-controller"],"operationId":"exportProjectTickets","parameters":[{"name":"projectId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"format","in":"query","required":false,"schema":{"type":"string","default":"csv"}},{"name":"status","in":"query","required":false,"schema":{"type":"string"}},{"name":"fromDate","in":"query","required":false,"schema":{"type":"string"}},{"name":"toDate","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/tickets/project/{projectId}/agent/{agentId}":{"get":{"tags":["ticket-controller"],"operationId":"getProjectTicketsByAgent","parameters":[{"name":"projectId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"agentId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":10}},{"name":"status","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/tickets/client/{clientId}":{"get":{"tags":["ticket-controller"],"operationId":"getTicketsByClientId","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Ticket"}}}}}}}},"/api/tickets/client-notes/{ticketId}/notes/external":{"get":{"tags":["ticket-controller"],"operationId":"getExternalNotesInternal","parameters":[{"name":"ticketId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"clientEmail","in":"query","required":false,"schema":{"type":"string"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/tickets/assigned-to/{userId}":{"get":{"tags":["ticket-controller"],"operationId":"getTicketsByAssignedToId","parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Ticket"}}}}}}}},"/api/tickets/all":{"get":{"tags":["ticket-controller"],"operationId":"getAllTicketsFlexible","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"sortBy","in":"query","required":false,"schema":{"type":"string","default":"id"}},{"name":"sortDir","in":"query","required":false,"schema":{"type":"string","default":"DESC"}},{"name":"autoSize","in":"query","required":false,"schema":{"type":"boolean","default":false}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/test/email-config":{"get":{"tags":["email-test-controller"],"operationId":"getEmailConfig","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/settings/user":{"get":{"tags":["settings-controller"],"operationId":"getUserSettings","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/settings/global":{"get":{"tags":["settings-controller"],"operationId":"getAllGlobalSettings","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/settings/export":{"get":{"tags":["settings-controller"],"operationId":"exportSettings","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/settings/categories":{"get":{"tags":["settings-controller"],"operationId":"getSettingsCategories","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/projects/{projectId}/tags/stats":{"get":{"tags":["🏷️ Project Tags"],"summary":"📊 Statistiques des tags","description":"Récupère les statistiques d'utilisation des tags d'un projet.\n\n### 📈 Métriques fournies\n- Nombre d'utilisations par tag\n- Tags les plus populaires\n- Répartition par période\n- Tendances d'utilisation\n\n### 💡 Utilisation\nIdéal pour analyser les types de problèmes les plus fréquents\n","operationId":"getProjectTagStats","parameters":[{"name":"projectId","in":"path","description":"ID du projet","required":true,"schema":{"type":"integer","format":"int64"},"example":1}],"responses":{"200":{"description":"✅ Statistiques récupérées","content":{"application/json":{"examples":{"Stats des tags":{"description":"Stats des tags","value":{"projectCode":"WEB","projectName":"Site Web E-commerce","tagUsageStats":[{"tagName":"database","usageCount":45,"percentage":28.5},{"tagName":"authentication","usageCount":32,"percentage":20.3},{"tagName":"performance","usageCount":28,"percentage":17.7}],"totalTickets":158,"period":"last_30_days"}}}}}}},"security":[{"bearerAuth":[]}]}},"/api/projects/{id}/stats":{"get":{"tags":["🏢 Projects"],"summary":"📊 Statistiques du projet","description":"Récupère les statistiques détaillées d'un projet.\n\n### 📈 Métriques incluses\n- Nombre de tickets par statut\n- Nombre d'agents assignés\n- Tickets ouverts/fermés\n- Temps de résolution moyen\n","operationId":"getProjectStats","parameters":[{"name":"id","in":"path","description":"ID du projet","required":true,"schema":{"type":"integer","format":"int64"},"example":1}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"bearerAuth":[]}]}},"/api/projects/{id}/full-details":{"get":{"tags":["🏢 Projects"],"summary":"📋 Détails complets du projet","description":"Récupère tous les détails d'un projet avec toutes les relations.\n\n### 📊 Données complètes\n- Informations du projet\n- Liste complète des agents\n- Relations avec les tickets\n- Métadonnées étendues\n","operationId":"getProjectFullDetails","parameters":[{"name":"id","in":"path","description":"ID du projet","required":true,"schema":{"type":"integer","format":"int64"},"example":1}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"bearerAuth":[]}]}},"/api/projects/user/{userId}":{"get":{"tags":["🏢 Projects"],"summary":"👤 Projets d'un utilisateur","description":"Récupère tous les projets associés à un utilisateur spécifique.\n\n### 🔐 Sécurité\n- Les utilisateurs ne peuvent voir que leurs propres projets\n- Les administrateurs peuvent voir tous les projets\n","operationId":"getUserProjects","parameters":[{"name":"userId","in":"path","description":"ID de l'utilisateur","required":true,"schema":{"type":"integer","format":"int64"},"example":5}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProjectDTO"}}}}}},"security":[{"bearerAuth":[]}]}},"/api/projects/active":{"get":{"tags":["🏢 Projects"],"summary":"✅ Récupérer les projets actifs","description":"Récupère uniquement les projets actifs (isActive = true).\n\n### 💡 Utilisation\nIdéal pour les listes déroulantes et la sélection de projets\n","operationId":"getActiveProjects","responses":{"200":{"description":"✅ Projets actifs récupérés","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectDTO"},"example":{"id":3,"name":"Application Mobile iOS","description":"Application mobile native pour iOS","isActive":true,"createdAt":"2025-06-25T09:00:00Z","agents":[{"id":2,"username":"pierre.dev","firstName":"Pierre","lastName":"Développeur","roles":["ROLE_DEV"]}],"ticketCount":15,"openTicketsCount":3}}}}},"security":[{"bearerAuth":[]}]}},"/api/profile-pictures/{userId}":{"get":{"tags":["📸 Profile Pictures"],"summary":"📸 Récupérer la photo de profil d'un utilisateur","description":"### Récupération de photo de profil (accès public)\n\n**🔓 Aucune authentification requise**\n\n**Fonctionnalités :**\n- Retourne la photo de profil de l'utilisateur\n- Support des formats d'image standards\n- Gestion automatique du type MIME\n- Mise en cache par le navigateur\n\n**Réponses possibles :**\n- `200` : Photo trouvée et retournée\n- `404` : Utilisateur inexistant ou pas de photo\n- `500` : Erreur serveur\n","operationId":"getProfilePicture","parameters":[{"name":"userId","in":"path","description":"ID de l'utilisateur","required":true,"schema":{"type":"integer","format":"int64"},"example":1}],"responses":{"200":{"description":"✅ Photo de profil trouvée","content":{"application/json":{"schema":{"type":"string","format":"binary"}}}},"500":{"description":"🔥 Erreur serveur","content":{"application/json":{"schema":{"type":"string","format":"binary"}}}},"404":{"description":"❌ Utilisateur non trouvé ou pas de photo","content":{"application/json":{"schema":{"type":"string","format":"binary"}}}}}}},"/api/profile-pictures/{userId}/info":{"get":{"tags":["📸 Profile Pictures"],"summary":"ℹ️ Informations sur la photo de profil","description":"### Métadonnées de la photo de profil\n\n**🔓 Accès public**\n\nRetourne les informations sur la photo sans exposer de données sensibles.\n","operationId":"getProfilePictureInfo","parameters":[{"name":"userId","in":"path","description":"ID de l'utilisateur","required":true,"schema":{"type":"integer","format":"int64"},"example":1}],"responses":{"404":{"description":"❌ Utilisateur non trouvé","content":{"application/json":{"schema":{"type":"object"}}}},"200":{"description":"✅ Informations retournées","content":{"application/json":{"schema":{"type":"object"}}}},"500":{"description":"🔥 Erreur serveur","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/profile-pictures/default":{"get":{"tags":["📸 Profile Pictures"],"summary":"📸 Photo de profil par défaut","description":"### Récupération de l'avatar par défaut\n\n**🔓 Accès public**\n\nRetourne une image par défaut quand l'utilisateur n'a pas de photo.\n","operationId":"getDefaultProfilePicture","responses":{"200":{"description":"✅ Avatar par défaut retourné","content":{"application/json":{"schema":{"type":"string","format":"binary"}}}},"404":{"description":"❌ Avatar par défaut non trouvé","content":{"application/json":{"schema":{"type":"string","format":"binary"}}}}}}},"/api/platforms/tickets/{ticketId}/messages/{messageId}/attachments":{"get":{"tags":["🌐 Platform API"],"summary":"Récupérer les attachements d'un message","operationId":"getMessageAttachments","parameters":[{"name":"ticketId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"messageId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"apiKey":[]}]}},"/api/platforms/tickets/{id}":{"get":{"tags":["🌐 Platform API"],"summary":"Récupérer un ticket spécifique","operationId":"getTicket","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"apiKey":[]}]}},"/api/platforms/stats":{"get":{"tags":["🌐 Platform API"],"summary":"Statistiques de la plateforme","operationId":"getStats","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"apiKey":[]}]}},"/api/platforms/attachments/{storedFilename}/view":{"get":{"tags":["🌐 Platform API"],"summary":"Visualiser un fichier","description":"Affiche un fichier directement dans le navigateur (images, PDF, etc.)","operationId":"viewAttachment","parameters":[{"name":"storedFilename","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"apiKey":[]}]}},"/api/platforms/attachments/{storedFilename}/download":{"get":{"tags":["🌐 Platform API"],"summary":"Télécharger un attachement","description":"Télécharge un fichier joint à un message","operationId":"downloadAttachment","parameters":[{"name":"storedFilename","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"apiKey":[]}]}},"/api/notifications/unread-count":{"get":{"tags":["notification-controller"],"operationId":"getUnreadCount_1","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnreadCountDTO"}}}}}}},"/api/notifications/stats":{"get":{"tags":["notification-controller"],"operationId":"getNotificationStats","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationStatsDTO"}}}}}}},"/api/knowledge/stats":{"get":{"tags":["📚 Base de Connaissances"],"summary":"📊 Statistiques","description":"Récupère les statistiques de la base de connaissances","operationId":"getKnowledgeStats","parameters":[{"name":"projectId","in":"query","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KnowledgeStatsDTO"}}}}}}},"/api/knowledge/projects/{projectId}/articles":{"get":{"tags":["📚 Base de Connaissances"],"summary":"🏢 Articles du projet","description":"Récupère tous les articles d'un projet spécifique","operationId":"getProjectArticles","parameters":[{"name":"projectId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20}},{"name":"sortBy","in":"query","required":false,"schema":{"type":"string","default":"updatedAt"}},{"name":"sortDir","in":"query","required":false,"schema":{"type":"string","default":"DESC"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PageKnowledgeArticleDTO"}}}}}}},"/api/knowledge/likes/stats":{"get":{"tags":["📚 Base de Connaissances"],"summary":"📊 Statistiques des likes","description":"Statistiques générales des likes","operationId":"getLikeStatistics","parameters":[{"name":"projectId","in":"query","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"startDate","in":"query","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"endDate","in":"query","required":false,"schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/knowledge/articles/{id}/full":{"get":{"tags":["📚 Base de Connaissances"],"summary":"📖 Article complet","description":"Récupère un article avec ses attachements","operationId":"getArticleWithAttachments","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/knowledge/articles/{articleId}/likes":{"get":{"tags":["📚 Base de Connaissances"],"summary":"👥 Liste des likes","description":"Récupère la liste des agents qui ont liké un article","operationId":"getArticleLikes","parameters":[{"name":"articleId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/knowledge/articles/{articleId}/like/status":{"get":{"tags":["📚 Base de Connaissances"],"summary":"❤️ Statut du like","description":"Vérifie si l'utilisateur actuel a liké cet article","operationId":"getLikeStatus","parameters":[{"name":"articleId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/knowledge/articles/search":{"get":{"tags":["📚 Base de Connaissances"],"summary":"🔍 Recherche avancée","description":"Recherche d'articles avec filtres","operationId":"searchArticles","parameters":[{"name":"category","in":"query","required":false,"schema":{"type":"string","enum":["TECHNICAL","PROCESS","TROUBLESHOOTING","FAQ","BEST_PRACTICES","ESCALATION"]}},{"name":"projectId","in":"query","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20}},{"name":"sortBy","in":"query","required":false,"schema":{"type":"string","default":"updatedAt"}},{"name":"sortDir","in":"query","required":false,"schema":{"type":"string","default":"DESC"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PageKnowledgeArticleDTO"}}}}}}},"/api/knowledge/articles/recent":{"get":{"tags":["📚 Base de Connaissances"],"summary":"🆕 Articles récents","description":"Récupère les articles récemment mis à jour","operationId":"getRecentArticles","parameters":[{"name":"projectId","in":"query","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":10}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/KnowledgeArticleDTO"}}}}}}}},"/api/knowledge/articles/popular":{"get":{"tags":["📚 Base de Connaissances"],"summary":"🔥 Articles populaires","description":"Récupère les articles les plus consultés","operationId":"getPopularArticles","parameters":[{"name":"projectId","in":"query","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":10}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/KnowledgeArticleDTO"}}}}}}}},"/api/knowledge/articles/category/{category}":{"get":{"tags":["📚 Base de Connaissances"],"summary":"📂 Articles par catégorie","description":"Récupère les articles d'une catégorie spécifique","operationId":"getArticlesByCategory","parameters":[{"name":"category","in":"path","required":true,"schema":{"type":"string","enum":["TECHNICAL","PROCESS","TROUBLESHOOTING","FAQ","BEST_PRACTICES","ESCALATION"]}},{"name":"projectId","in":"query","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":0}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","format":"int32","default":20}},{"name":"sortBy","in":"query","required":false,"schema":{"type":"string","default":"updatedAt"}},{"name":"sortDir","in":"query","required":false,"schema":{"type":"string","default":"DESC"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PageKnowledgeArticleDTO"}}}}}}},"/api/keys/{keyId}/stats":{"get":{"tags":["🔑 API Keys"],"summary":"Statistiques d'une clé API","description":"Récupère les statistiques d'utilisation d'une clé API","operationId":"getApiKeyStats","parameters":[{"name":"keyId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"bearerAuth":[]}]}},"/api/keys/permissions":{"get":{"tags":["🔑 API Keys"],"summary":"Lister les permissions disponibles","description":"Récupère toutes les permissions disponibles pour les clés API","operationId":"getAvailablePermissions","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"bearerAuth":[]}]}},"/api/keys/admin/stats":{"get":{"tags":["🔑 API Keys"],"summary":"Statistiques globales des API keys","description":"Statistiques générales pour les administrateurs","operationId":"getGlobalStats","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"bearerAuth":[]}]}},"/api/external/tickets":{"get":{"tags":["� External API"],"summary":"📋 Lister les tickets d'un client","description":"## Récupérer les tickets d'un client\n\n### 🔍 Filtres disponibles\n- **Statut** : Filtrer par statut de ticket (OPEN, IN_PROGRESS, CLOSED, etc.)\n- **Priorité** : Filtrer par niveau de priorité (LOW, MEDIUM, HIGH, URGENT)\n- **Projet** : Filtrer par projet spécifique\n\n### 📊 Pagination et tri\n- Support complet de la pagination\n- Tri par date, priorité, statut\n- Ordre croissant ou décroissant\n\n### 📈 Informations incluses\n- Liste paginée des tickets\n- Résumé des informations client\n- Statistiques rapides\n- Informations de navigation\n","operationId":"getClientTickets","parameters":[{"name":"X-Marketplace-Token","in":"header","description":"🔑 Token marketplace (Base64 JSON avec email client)","required":true,"schema":{"type":"string"},"example":"eyJlbWFpbCI6ImNsaWVudEBleGFtcGxlLmNvbSJ9"},{"name":"X-Platform-ID","in":"header","description":"🏷️ Identifiant de la plateforme marketplace","required":false,"schema":{"type":"string"},"example":"shopify-store-123"},{"name":"page","in":"query","description":"📄 Numéro de page (commence à 0)","required":false,"schema":{"type":"integer","format":"int32","default":0},"example":0},{"name":"size","in":"query","description":"📊 Taille de page (nombre d'éléments)","required":false,"schema":{"type":"integer","format":"int32","default":10},"example":10},{"name":"sortBy","in":"query","description":"🔤 Champ de tri","required":false,"schema":{"type":"string","default":"createdAt"},"example":"createdAt"},{"name":"sortDir","in":"query","description":"⬆️ Direction du tri (ASC ou DESC)","required":false,"schema":{"type":"string","default":"DESC"},"example":"DESC"},{"name":"status","in":"query","description":"🏷️ Filtrer par statut","required":false,"schema":{"type":"string"},"example":"OPEN"},{"name":"priority","in":"query","description":"⚡ Filtrer par priorité","required":false,"schema":{"type":"string"},"example":"HIGH"},{"name":"projectId","in":"query","description":"🏢 Filtrer par projet","required":false,"schema":{"type":"integer","format":"int64"},"example":1}],"responses":{"200":{"description":"✅ Client inexistant","content":{"application/json":{"examples":{"Aucun client":{"description":"Aucun client","value":{"tickets":[],"totalElements":0,"totalPages":0,"currentPage":0,"pageSize":10,"clientExists":false,"message":"No client found with this email"}}}}}},"401":{"description":"🔒 Token invalide","content":{"application/json":{"examples":{"Token invalide":{"description":"Token invalide","value":{"message":"Invalid marketplace token"}}}}}}}}},"/api/external/tickets/{ticketId}":{"get":{"tags":["🏪 External API","� External API"],"summary":"🔍 Récupérer un ticket existant","description":"## Récupérer les détails d'un ticket\n\n### 🔐 Sécurité\n- Le ticket doit appartenir au client identifié par le token\n- Accès refusé si le client ne correspond pas\n\n### 📋 Informations retournées\n- Détails complets du ticket\n- **Informations complètes de l'agent** (nom, prénom, email)\n- Informations du projet associé\n- **Historique du ticket** (création, changements de statut)\n- Messages du ticket (si autorisé)\n\n### 📊 Paramètres optionnels\n- `includeHistory` : Inclure l'historique détaillé du ticket\n- `includeMessages` : Inclure les derniers messages\n","operationId":"getTicket_1","parameters":[{"name":"ticketId","in":"path","description":"🆔 Identifiant unique du ticket","required":true,"schema":{"type":"integer","format":"int64"},"example":123},{"name":"X-Marketplace-Token","in":"header","description":"🔑 Token marketplace (Base64 JSON avec email client)","required":true,"schema":{"type":"string"},"example":"eyJlbWFpbCI6ImNsaWVudEBleGFtcGxlLmNvbSJ9"},{"name":"X-Platform-ID","in":"header","description":"🏷️ Identifiant de la plateforme marketplace","required":false,"schema":{"type":"string"},"example":"shopify-store-123"},{"name":"includeHistory","in":"query","description":"📋 Inclure l'historique du ticket","required":false,"schema":{"type":"boolean","default":true},"example":true},{"name":"includeMessages","in":"query","description":"💬 Inclure les derniers messages","required":false,"schema":{"type":"boolean","default":false},"example":true},{"name":"messageLimit","in":"query","description":"📊 Nombre de messages récents à inclure","required":false,"schema":{"type":"integer","format":"int32","default":5},"example":5}],"responses":{"200":{"description":"✅ Ticket récupéré avec succès","content":{"application/json":{"examples":{"Ticket complet":{"description":"Ticket complet","value":{"ticket":{"id":123,"title":"Problème de connexion","description":"Impossible de se connecter...","status":"IN_PROGRESS","priority":"HIGH","createdAt":"2025-01-15T10:30:00Z","updatedAt":"2025-01-15T14:20:00Z","sourceType":"MARKETPLACE"},"assignedAgent":{"id":2,"firstName":"Marie","lastName":"Martin","email":"marie.martin@systalink.fr","username":"mmartin","role":"DEV","isActive":true},"project":{"id":1,"code":"WEB","name":"Site Web Corporate"},"client":{"id":45,"email":"client@example.com","firstName":"Jean","lastName":"Dupont"},"history":[{"date":"2025-01-15T10:30:00Z","action":"CREATED","description":"Ticket créé par Jean Dupont","previousValue":null,"newValue":"OPEN","actor":"Jean Dupont","actorType":"CLIENT"},{"date":"2025-01-15T10:45:00Z","action":"ASSIGNED","description":"Ticket assigné à Marie Martin","previousValue":null,"newValue":"Marie Martin","actor":"System","actorType":"SYSTEM"},{"date":"2025-01-15T11:00:00Z","action":"STATUS_CHANGED","description":"Statut changé de OPEN à IN_PROGRESS","previousValue":"OPEN","newValue":"IN_PROGRESS","actor":"Marie Martin","actorType":"AGENT"}],"recentMessages":[{"id":1,"content":"Nous analysons le problème","createdAt":"2025-01-15T11:00:00Z","author":"Marie Martin","direction":"OUTBOUND"}],"statistics":{"totalMessages":8,"unreadMessages":2,"daysSinceCreation":2,"lastActivity":"2025-01-15T14:20:00Z"}}}}}}},"404":{"description":"❌ Ticket non trouvé","content":{"application/json":{"schema":{"type":"object"}}}},"403":{"description":"🚫 Accès refusé","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"🔒 Token invalide","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/external/tickets/{ticketId}/note":{"get":{"tags":["🏪 External API","� External API"],"summary":"📋 Récupérer les notes d'un ticket","description":"## Consulter l'historique des notes et messages\n\n### 🔐 Sécurité\n- Le ticket doit appartenir au client identifié par le token\n- Seules les notes non-privées sont visibles pour les clients\n\n### 📊 Pagination\n- Support de la pagination pour les gros volumes\n- Tri par date (plus récent en premier)\n- Filtrage par type de message\n\n### 💡 Utilisation\n- Consulter l'historique des échanges\n- Suivre l'évolution du ticket\n- Retrouver des informations précédentes\n","operationId":"getTicketNotes","parameters":[{"name":"ticketId","in":"path","description":"🆔 Identifiant unique du ticket","required":true,"schema":{"type":"integer","format":"int64"},"example":123},{"name":"X-Marketplace-Token","in":"header","description":"🔑 Token marketplace (Base64 JSON avec email client)","required":true,"schema":{"type":"string"},"example":"eyJlbWFpbCI6ImNsaWVudEBleGFtcGxlLmNvbSJ9"},{"name":"X-Platform-ID","in":"header","description":"🏷️ Identifiant de la plateforme marketplace","required":false,"schema":{"type":"string"},"example":"shopify-store-123"},{"name":"page","in":"query","description":"📄 Numéro de page (commence à 0)","required":false,"schema":{"type":"integer","format":"int32","default":0},"example":0},{"name":"size","in":"query","description":"📊 Taille de page (nombre d'éléments)","required":false,"schema":{"type":"integer","format":"int32","default":20},"example":20}],"responses":{"404":{"description":"❌ Ticket non trouvé","content":{"application/json":{"schema":{"type":"object"}}}},"200":{"description":"✅ Notes récupérées avec succès","content":{"application/json":{"examples":{"Liste des notes":{"description":"Liste des notes","value":{"ticket":{"id":123,"title":"Problème de connexion","status":"IN_PROGRESS"},"messages":[{"id":456,"content":"Note du client: J'ai essayé la solution proposée","createdAt":"2025-01-15T15:30:00Z","author":"Jean Dupont","type":"CLIENT_NOTE","direction":"INBOUND"},{"id":455,"content":"Réponse de l'agent: Essayez de redémarrer le serveur","createdAt":"2025-01-15T11:00:00Z","author":"Marie Martin","type":"AGENT_RESPONSE","direction":"OUTBOUND"}],"totalMessages":25,"currentPage":0,"totalPages":3,"hasNext":true}}}}}},"403":{"description":"🚫 Accès refusé","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/external/tickets/statistics":{"get":{"tags":["� External API"],"summary":"📊 Statistiques des tickets client","description":"## Statistiques détaillées des tickets\n\n### 📈 Métriques incluses\n- **Nombre total** de tickets créés\n- **Répartition par statut** (ouverts, en cours, fermés)\n- **Répartition par priorité** (faible, moyenne, haute, urgente)\n- **Répartition par projet** (si applicable)\n- **Statistiques temporelles** (tickets par mois)\n\n### 📊 Analyse des tendances\n- Évolution du nombre de tickets\n- Temps moyen de résolution\n- Satisfaction client\n- Performance par projet\n\n### 💡 Utilisation\n- Tableaux de bord client\n- Rapports de performance\n- Analyse des tendances\n- Suivi de la qualité de service\n","operationId":"getClientTicketStatistics","parameters":[{"name":"X-Marketplace-Token","in":"header","description":"🔑 Token marketplace (Base64 JSON avec email client)","required":true,"schema":{"type":"string"},"example":"eyJlbWFpbCI6ImNsaWVudEBleGFtcGxlLmNvbSJ9"},{"name":"X-Platform-ID","in":"header","description":"🏷️ Identifiant de la plateforme marketplace","required":false,"schema":{"type":"string"},"example":"shopify-store-123"}],"responses":{"200":{"description":"✅ Client inexistant","content":{"application/json":{"examples":{"Aucun client":{"description":"Aucun client","value":{"clientExists":false,"message":"No client found with this email"}}}}}},"401":{"description":"🔒 Token invalide","content":{"application/json":{"examples":{"Token invalide":{"description":"Token invalide","value":{"message":"Invalid marketplace token"}}}}}}}}},"/api/external/clients/check":{"get":{"tags":["� External API"],"summary":"👥 Vérifier l'existence d'un client","description":"## Vérifier si un client existe\n\n### 🔍 Recherche par\n- **Email** : Recherche principale (peut utiliser l'email du token)\n- **ID Client** : Recherche par identifiant unique\n\n### 📋 Informations retournées\n- Statut d'existence du client\n- Informations de base si trouvé\n- Suggestions de création si absent\n\n### 💡 Cas d'usage\n- Vérification avant création de ticket\n- Synchronisation des données client\n- Validation d'email\n","operationId":"checkClientExists","parameters":[{"name":"email","in":"query","description":"📧 Email du client à vérifier (optionnel si dans le token)","required":false,"schema":{"type":"string"},"example":"client@example.com"},{"name":"clientId","in":"query","description":"🆔 ID du client à vérifier","required":false,"schema":{"type":"integer","format":"int64"},"example":45},{"name":"X-Marketplace-Token","in":"header","description":"🔑 Token marketplace (Base64 JSON avec email client)","required":true,"schema":{"type":"string"},"example":"eyJlbWFpbCI6ImNsaWVudEBleGFtcGxlLmNvbSJ9"},{"name":"X-Platform-ID","in":"header","description":"🏷️ Identifiant de la plateforme marketplace","required":false,"schema":{"type":"string"},"example":"shopify-store-123"}],"responses":{"200":{"description":"✅ Vérification effectuée","content":{"application/json":{"examples":{"Client existant":{"description":"Client existant","value":{"exists":true,"client":{"id":45,"email":"client@example.com","firstName":"Jean","lastName":"Dupont","company":"Entreprise SARL"}}},"Client inexistant":{"description":"Client inexistant","value":{"exists":false,"client":null}}}}}},"401":{"description":"🔒 Token invalide","content":{"application/json":{"examples":{"Token invalide":{"description":"Token invalide","value":{"message":"Invalid marketplace token"}}}}}},"400":{"description":"❌ Paramètres manquants","content":{"application/json":{"examples":{"Paramètres requis":{"description":"Paramètres requis","value":{"message":"Either email or clientId must be provided"}}}}}}}}},"/api/docs/quick-start":{"get":{"tags":["📚 Documentation"],"summary":"🚀 Guide de démarrage rapide","description":"### Démarrage rapide en 5 étapes\n\nCe guide vous aide à commencer rapidement avec l'API Support Client.\n","operationId":"getQuickStart","responses":{"200":{"description":"Guide de démarrage","content":{"application/json":{"examples":{"Guide complet":{"description":"Guide complet","value":{"title":"🚀 Démarrage Rapide - API Support Client","steps":[{"step":1,"title":"🔑 Authentification","description":"Connectez-vous pour obtenir un token JWT","endpoint":"POST /api/auth/login","example":{"email":"admin@systalink.fr","password":"votre_mot_de_passe"}},{"step":2,"title":"🔒 Autorisation","description":"Utilisez le token dans vos requêtes","header":"Authorization: Bearer <votre_token>"},{"step":3,"title":"🎫 Créer un ticket","description":"Créez votre premier ticket de support","endpoint":"POST /api/tickets"},{"step":4,"title":"📋 Lister les tickets","description":"Récupérez la liste des tickets","endpoint":"GET /api/tickets"},{"step":5,"title":"🎉 Explorez !","description":"Découvrez tous les autres endpoints","tip":"Utilisez les filtres et la pagination pour optimiser vos requêtes"}],"tips":["💡 Utilisez Swagger UI pour tester directement","📖 Consultez les exemples dans chaque endpoint","🔍 Utilisez les filtres pour optimiser les performances","📊 Exploitez les statistiques pour vos dashboards"]}}}}}}}}},"/api/docs/permissions":{"get":{"tags":["📚 Documentation"],"summary":"🔐 Guide des permissions et rôles","description":"### Système de permissions par rôles\n\nComprendre qui peut faire quoi dans l'application.\n","operationId":"getPermissionsGuide","responses":{"200":{"description":"Guide des permissions","content":{"application/json":{"examples":{"Permissions détaillées":{"description":"Permissions détaillées","value":{"roles":{"ROLE_ADMIN":{"name":"👑 Administrateur","description":"Accès complet au système","permissions":["Créer/modifier/supprimer tous les tickets","Gérer les utilisateurs et rôles","Configurer les projets et tags","Accès aux statistiques globales","Administration système"],"endpoints":["ALL"]},"ROLE_DEV":{"name":"💻 Développeur","description":"Gestion des tickets techniques","permissions":["Tickets assignés et projets","Résolution de bugs","Commentaires techniques"],"tags":["bug","development","code","API"]},"ROLE_OPERATIONS":{"name":"⚙️ Opérations","description":"Infrastructure et systèmes","permissions":["Tickets infrastructure","Problèmes serveurs/BDD","Maintenance système"],"tags":["database","server","infrastructure","hosting"]},"ROLE_SECURITY":{"name":"🛡️ Sécurité","description":"Sécurité et protection","permissions":["Tickets sécurité","Authentification","Firewall et SSL"],"tags":["security","firewall","authentication","ssl"]},"ROLE_SALES":{"name":"💰 Commercial","description":"Ventes et facturation","permissions":["Tickets commerciaux","Facturation","Support client"],"tags":["billing","payment","invoice","sales"]},"ROLE_CLIENT":{"name":"👤 Client","description":"Utilisateur final","permissions":["Ses propres tickets uniquement","Création de nouveaux tickets","Consultation de l'historique"],"restrictions":["Accès limité à ses données"]}}}}}}}}}}},"/api/docs/health":{"get":{"tags":["📚 Documentation"],"summary":"💚 Statut de l'API","description":"Vérifier que l'API fonctionne correctement","operationId":"health","responses":{"200":{"description":"API opérationnelle","content":{"application/json":{"examples":{"Statut OK":{"description":"Statut OK","value":{"status":"UP","message":"🚀 API Support Client opérationnelle","version":"1.0.0","timestamp":"2025-06-25T12:00:00Z","endpoints":{"documentation":"/swagger-ui.html","api-docs":"/v3/api-docs","health":"/api/docs/health"}}}}}}}}}},"/api/docs/examples":{"get":{"tags":["📚 Documentation"],"summary":"📋 Exemples d'utilisation","description":"### Exemples pratiques d'utilisation de l'API\n\nScénarios courants avec exemples de requêtes et réponses.\n","operationId":"getExamples","responses":{"200":{"description":"Exemples pratiques","content":{"application/json":{"examples":{"Scénarios d'usage":{"description":"Scénarios d'usage","value":{"scenarios":[{"title":"🎫 Créer un ticket avec nouveau client","description":"Créer un ticket pour un client qui n'existe pas encore","steps":[{"action":"POST /api/tickets","data":{"title":"Problème de connexion","description":"Impossible de me connecter depuis ce matin","priority":"HIGH","projectId":1,"clientFirstName":"Jean","clientLastName":"Dupont","clientEmail":"jean@entreprise.com"}}],"result":"Le client sera créé automatiquement"},{"title":"📊 Obtenir des statistiques","description":"Récupérer les métriques d'un projet","steps":["GET /api/projects/1/stats"]},{"title":"🔍 Recherche avancée","description":"Filtrer les tickets par critères","steps":["GET /api/tickets?status=OPEN&priority=HIGH&page=0&size=10"]}]}}}}}}}}},"/api/docs/errors":{"get":{"tags":["📚 Documentation"],"summary":"❌ Codes d'erreur et solutions","description":"### Guide des erreurs communes et leurs solutions\n\nComprendre les codes d'erreur HTTP et comment les résoudre.\n","operationId":"getErrorGuide","responses":{"200":{"description":"Guide des erreurs","content":{"application/json":{"examples":{"Codes d'erreur":{"description":"Codes d'erreur","value":{"errorGuide":{"400":{"name":"Bad Request","description":"Données invalides ou manquantes","solutions":["Vérifiez le format JSON","Validez les champs obligatoires","Respectez les contraintes de validation"],"example":"Titre de ticket manquant"},"401":{"name":"Unauthorized","description":"Token manquant ou invalide","solutions":["Connectez-vous via /api/auth/login","Vérifiez l'en-tête Authorization","Le token a peut-être expiré"],"example":"Token JWT expiré"},"403":{"name":"Forbidden","description":"Permissions insuffisantes","solutions":["Vérifiez vos rôles utilisateur","Contactez un administrateur","Utilisez un compte autorisé"],"example":"Seuls les ADMIN peuvent créer des utilisateurs"},"404":{"name":"Not Found","description":"Ressource introuvable","solutions":["Vérifiez l'ID de la ressource","La ressource a peut-être été supprimée","Utilisez GET pour lister les ressources"],"example":"Ticket #999 n'existe pas"},"500":{"name":"Internal Server Error","description":"Erreur serveur interne","solutions":["Réessayez plus tard","Contactez le support technique","Vérifiez les logs serveur"],"example":"Erreur de base de données"}}}}}}}}}}},"/api/clients/stats":{"get":{"tags":["client-controller"],"operationId":"getClientStats","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/auth/validate-reset-token/{token}":{"get":{"tags":["🔐 Authentication"],"summary":"✅ Valider un token de réinitialisation","description":"### Validation d'un token de réinitialisation\n\nVérifie si un token de réinitialisation est valide et n'a pas expiré.\n\n**Utilisation :**\n- Appelé par le frontend avant d'afficher le formulaire\n- Vérifie l'expiration (24h max)\n- Vérifie si le token n'a pas déjà été utilisé\n","operationId":"validateResetToken","parameters":[{"name":"token","in":"path","description":"Token de réinitialisation à valider","required":true,"schema":{"type":"string"},"example":"abcd1234efgh5678"}],"responses":{"400":{"description":"❌ Token invalide ou expiré","content":{"application/json":{"schema":{"type":"object"}}}},"200":{"description":"✅ Token valide","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/attachments":{"get":{"tags":["📎 Attachments"],"summary":"📋 Lister les attachements","description":"Récupère tous les attachements d'une entité avec pagination optionnelle","operationId":"getAttachments","parameters":[{"name":"entityType","in":"query","description":"🏷️ Type d'entité","required":true,"schema":{"type":"string"}},{"name":"entityId","in":"query","description":"🆔 ID de l'entité","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"page","in":"query","description":"📄 Pagination - page","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"size","in":"query","description":"📊 Pagination - taille","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"publicOnly","in":"query","description":"🌐 Seulement les fichiers publics","required":false,"schema":{"type":"boolean","default":false}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/attachments/{storedFilename}/preview":{"get":{"tags":["📎 Attachments"],"summary":"🖼️ Prévisualiser une image","description":"Affiche une image en ligne (pour les types image uniquement)","operationId":"previewFile","parameters":[{"name":"storedFilename","in":"path","description":"📁 Nom de fichier stocké","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"string","format":"binary"}}}}}}},"/api/attachments/{storedFilename}/download":{"get":{"tags":["📎 Attachments"],"summary":"📥 Télécharger un fichier","description":"Télécharge un fichier attaché par son nom de stockage","operationId":"downloadFile","parameters":[{"name":"storedFilename","in":"path","description":"📁 Nom de fichier stocké","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"string","format":"binary"}}}}}}},"/api/attachments/stats":{"get":{"tags":["📎 Attachments"],"summary":"📊 Statistiques des attachements","description":"Récupère les statistiques des attachements d'une entité","operationId":"getAttachmentStats","parameters":[{"name":"entityType","in":"query","description":"🏷️ Type d'entité","required":true,"schema":{"type":"string"}},{"name":"entityId","in":"query","description":"🆔 ID de l'entité","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/notifications/{id}":{"delete":{"tags":["notification-controller"],"operationId":"deleteNotification","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}}}}},"/api/knowledge/articles/{articleId}/attachments/{attachmentId}":{"delete":{"tags":["📚 Base de Connaissances"],"summary":"🗑️ Supprimer un fichier","description":"Supprime un fichier attaché à un article","operationId":"deleteArticleAttachment","parameters":[{"name":"articleId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"attachmentId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/keys/{keyId}/delete":{"delete":{"tags":["🔑 API Keys"],"summary":"Supprimer complètement une clé API","description":"Supprime définitivement une clé API de la base de données.\n\n**⚠️ Attention :**\n- Cette action est irréversible\n- La clé sera complètement supprimée (pas seulement désactivée)\n- Nécessite une confirmation par mot de passe\n- Tous les services utilisant cette clé cesseront de fonctionner\n","operationId":"deleteApiKey","parameters":[{"name":"keyId","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"}}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"bearerAuth":[]}]}},"/api/keys/batch-delete":{"delete":{"tags":["🔑 API Keys"],"summary":"Supprimer plusieurs clés API","description":"Supprime définitivement plusieurs clés API en une fois (Admin uniquement)","operationId":"deleteMultipleApiKeys","requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"object"}}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}},"security":[{"bearerAuth":[]}]}},"/api/clients/{id}/services/{serviceName}":{"delete":{"tags":["client-controller"],"operationId":"removeClientService","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}},{"name":"serviceName","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}}},"components":{"schemas":{"ApiKey":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"keyValue":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"isActive":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"lastUsedAt":{"type":"string","format":"date-time"},"expiresAt":{"type":"string","format":"date-time"},"permissions":{"uniqueItems":true,"type":"array","items":{"type":"string","enum":["READ_TICKETS","READ_USERS","READ_PROJECTS","READ_STATS","WRITE_TICKETS","WRITE_USERS","WRITE_PROJECTS","ADMIN_ACCESS","EXTERNAL_API","DELETE_OPERATIONS","SEND_NOTIFICATIONS","ACCESS_INTERNAL_NOTES"]}},"rateLimitPerHour":{"type":"integer","format":"int32"},"requestCountToday":{"type":"integer","format":"int64"},"lastRequestDate":{"type":"string","format":"date-time"},"expired":{"type":"boolean"},"rateLimitExceeded":{"type":"boolean"}}},"Project":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"description":{"type":"string"},"code":{"type":"string"},"isActive":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"webhookUrl":{"type":"string"},"contactEmail":{"type":"string"},"allowExternalApi":{"type":"boolean"},"externalIdentifier":{"type":"string"},"projectApiKeys":{"uniqueItems":true,"type":"array","items":{"$ref":"#/components/schemas/ApiKey"}}}},"Tag":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"project":{"$ref":"#/components/schemas/Project"},"tickets":{"uniqueItems":true,"type":"array","items":{"$ref":"#/components/schemas/Ticket"}},"globalTag":{"type":"boolean"}}},"User":{"required":["email","password","username"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"username":{"maxLength":20,"minLength":0,"type":"string"},"email":{"maxLength":50,"minLength":0,"type":"string"},"password":{"maxLength":120,"minLength":0,"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"phone":{"type":"string"},"company":{"type":"string"},"profilePicturePath":{"type":"string"},"profilePictureFilename":{"type":"string"},"profilePictureContentType":{"type":"string"},"profilePictureSize":{"type":"integer","format":"int64"},"projects":{"uniqueItems":true,"type":"array","items":{"$ref":"#/components/schemas/Project"}}}},"TicketRequest":{"required":["title"],"type":"object","properties":{"title":{"maxLength":255,"minLength":5,"type":"string"},"description":{"maxLength":4000,"minLength":0,"type":"string"},"priority":{"type":"string","enum":["LOW","MEDIUM","HIGH","URGENT"]},"status":{"type":"string","enum":["OPEN","IN_PROGRESS","PENDING_CLIENT","PENDING_THIRD_PARTY","RESOLVED","CLOSED","REOPENED"]},"tags":{"type":"array","items":{"type":"string"}},"notes":{"maxLength":2000,"minLength":0,"type":"string"},"projectId":{"type":"integer","format":"int64"},"clientId":{"type":"integer","format":"int64"},"clientFirstName":{"maxLength":50,"minLength":2,"type":"string"},"clientLastName":{"maxLength":50,"minLength":2,"type":"string"},"clientEmail":{"type":"string"},"clientPhone":{"maxLength":20,"minLength":0,"type":"string"},"clientCompany":{"maxLength":100,"minLength":0,"type":"string"}}},"Ticket":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"title":{"type":"string"},"description":{"type":"string"},"notes":{"type":"string"},"status":{"type":"string","enum":["OPEN","IN_PROGRESS","PENDING_CLIENT","PENDING_THIRD_PARTY","RESOLVED","CLOSED","REOPENED"]},"priority":{"type":"string","enum":["LOW","MEDIUM","HIGH","URGENT"]},"assignedTo":{"$ref":"#/components/schemas/User"},"client":{"$ref":"#/components/schemas/User"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"resolvedAt":{"type":"string","format":"date-time"},"sourceType":{"type":"string","enum":["EMAIL","WEB_FORM","PHONE","CHAT","API","SYSTALINK_MARKETPLACE","INTERNAL"]},"sourceReference":{"type":"string"},"messageCount":{"type":"integer","format":"int32"},"project":{"$ref":"#/components/schemas/Project"}}},"KnowledgeCreateRequest":{"required":["category","content","priority","summary","title"],"type":"object","properties":{"title":{"maxLength":500,"minLength":0,"type":"string"},"content":{"type":"string"},"summary":{"maxLength":1000,"minLength":0,"type":"string"},"category":{"type":"string","enum":["TECHNICAL","PROCESS","TROUBLESHOOTING","FAQ","BEST_PRACTICES","ESCALATION"]},"priority":{"type":"string","enum":["LOW","MEDIUM","HIGH","CRITICAL"]},"tags":{"uniqueItems":true,"type":"array","items":{"type":"string"}},"projectId":{"type":"integer","format":"int64"},"relatedTicketIds":{"type":"array","items":{"type":"integer","format":"int64"}}}},"ApiKeyRequest":{"required":["name"],"type":"object","properties":{"name":{"maxLength":100,"minLength":0,"type":"string"},"description":{"maxLength":500,"minLength":0,"type":"string"},"permissions":{"uniqueItems":true,"type":"array","items":{"type":"string"}},"rateLimitPerHour":{"type":"integer","format":"int32"},"expiresAt":{"type":"string","format":"date-time"},"restrictedToProjectId":{"type":"integer","format":"int64"}}},"ClientRequest":{"required":["company","email","firstName","lastName"],"type":"object","properties":{"company":{"maxLength":100,"minLength":2,"type":"string"},"firstName":{"maxLength":50,"minLength":2,"type":"string"},"lastName":{"maxLength":50,"minLength":2,"type":"string"},"email":{"type":"string"},"phone":{"maxLength":20,"minLength":0,"type":"string"},"services":{"type":"array","items":{"type":"string"}}}},"SettingsDTO":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"key":{"type":"string"},"value":{"type":"string"},"defaultValue":{"type":"string"},"category":{"type":"string","enum":["GENERAL","NOTIFICATIONS","APPEARANCE","SECURITY","SYSTEM","EMAIL","INTEGRATIONS"]},"description":{"type":"string"},"valueType":{"type":"string"},"isPublic":{"type":"boolean"},"updatedAt":{"type":"string","format":"date-time"},"general":{"type":"object","additionalProperties":{"type":"string"}},"notifications":{"type":"object","additionalProperties":{"type":"string"}},"appearance":{"type":"object","additionalProperties":{"type":"string"}},"security":{"type":"object","additionalProperties":{"type":"string"}},"system":{"type":"object","additionalProperties":{"type":"string"}}}},"ProjectDTO":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"description":{"type":"string"},"code":{"type":"string"},"isActive":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"assignedAgentsCount":{"type":"integer","format":"int32"},"ticketsCount":{"type":"integer","format":"int32"},"assignedAgentNames":{"type":"array","items":{"type":"string"}}}},"PlatformTicketRequest":{"required":["clientEmail","description","title"],"type":"object","properties":{"title":{"type":"string"},"description":{"type":"string"},"clientEmail":{"type":"string"},"clientName":{"type":"string"},"clientLastName":{"type":"string"},"clientPhone":{"type":"string"},"clientCompany":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"priority":{"type":"string","enum":["LOW","MEDIUM","HIGH","URGENT"]},"externalReference":{"type":"string"},"metadata":{"type":"object","additionalProperties":{"type":"object"}}}},"CreateNotificationDTO":{"required":["message","title","type"],"type":"object","properties":{"title":{"type":"string"},"message":{"type":"string"},"type":{"type":"string"},"actionUrl":{"type":"string"},"priority":{"type":"string"},"relatedEntity":{"$ref":"#/components/schemas/RelatedEntityDTO"}}},"RelatedEntityDTO":{"type":"object","properties":{"type":{"type":"string"},"id":{"type":"string"},"name":{"type":"string"}}},"NotificationDTO":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"message":{"type":"string"},"type":{"type":"string"},"isRead":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"actionUrl":{"type":"string"},"priority":{"type":"string"},"relatedEntity":{"$ref":"#/components/schemas/RelatedEntityDTO"}}},"SmartSearchRequest":{"type":"object","properties":{"title":{"type":"string"},"description":{"type":"string"},"projectId":{"type":"integer","format":"int64"}}},"AttachmentDTO":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"originalFilename":{"type":"string"},"storedFilename":{"type":"string"},"fileSize":{"type":"integer","format":"int64"},"fileSizeFormatted":{"type":"string"},"contentType":{"type":"string"},"description":{"type":"string"},"isPublic":{"type":"boolean"},"uploadedAt":{"type":"string","format":"date-time"},"downloadCount":{"type":"integer","format":"int32"},"downloadUrl":{"type":"string"},"previewUrl":{"type":"string"},"uploadedBy":{"$ref":"#/components/schemas/UserSimpleDTO"},"fileCategory":{"type":"string"},"image":{"type":"boolean"},"document":{"type":"boolean"}}},"KnowledgeArticleDTO":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"title":{"type":"string"},"content":{"type":"string"},"summary":{"type":"string"},"category":{"type":"string","enum":["TECHNICAL","PROCESS","TROUBLESHOOTING","FAQ","BEST_PRACTICES","ESCALATION"]},"priority":{"type":"string","enum":["LOW","MEDIUM","HIGH","CRITICAL"]},"status":{"type":"string","enum":["DRAFT","PUBLISHED","ARCHIVED","UNDER_REVIEW"]},"tags":{"uniqueItems":true,"type":"array","items":{"type":"string"}},"projectId":{"type":"integer","format":"int64"},"projectName":{"type":"string"},"authorId":{"type":"integer","format":"int64"},"authorName":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"lastModifiedBy":{"type":"string"},"viewCount":{"type":"integer","format":"int32"},"helpfulCount":{"type":"integer","format":"int32"},"relatedTicketIds":{"type":"array","items":{"type":"integer","format":"int64"}},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/AttachmentDTO"}},"attachmentCount":{"type":"integer","format":"int32"},"hasAttachments":{"type":"boolean"},"isLikedByCurrentUser":{"type":"boolean"},"likedByAgents":{"type":"array","items":{"$ref":"#/components/schemas/KnowledgeLikeDTO"}}}},"KnowledgeLikeDTO":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"articleId":{"type":"integer","format":"int64"},"articleTitle":{"type":"string"},"userId":{"type":"integer","format":"int64"},"userName":{"type":"string"},"userFirstName":{"type":"string"},"userLastName":{"type":"string"},"userEmail":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"ipAddress":{"type":"string"}}},"UserSimpleDTO":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"username":{"type":"string"},"email":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"profilePictureUrl":{"type":"string"}}},"ResetPasswordRequest":{"required":["confirmPassword","newPassword","token"],"type":"object","properties":{"token":{"type":"string"},"newPassword":{"maxLength":2147483647,"minLength":6,"type":"string"},"confirmPassword":{"type":"string"}},"description":"Données de réinitialisation"},"MessageResponse":{"type":"object","properties":{"message":{"type":"string"}}},"LoginRequest":{"required":["email","password"],"type":"object","properties":{"email":{"type":"string"},"password":{"type":"string"}},"description":"Identifiants de connexion"},"JwtResponse":{"type":"object","properties":{"token":{"type":"string"},"type":{"type":"string"},"id":{"type":"integer","format":"int64"},"username":{"type":"string"},"email":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"phone":{"type":"string"},"company":{"type":"string"},"roles":{"type":"array","items":{"type":"string"}}}},"ForgotPasswordRequest":{"required":["email"],"type":"object","properties":{"email":{"type":"string"}},"description":"Email du compte à réinitialiser"},"PageTicketDTO":{"type":"object","properties":{"totalElements":{"type":"integer","format":"int64"},"totalPages":{"type":"integer","format":"int32"},"pageable":{"$ref":"#/components/schemas/PageableObject"},"size":{"type":"integer","format":"int32"},"content":{"type":"array","items":{"$ref":"#/components/schemas/TicketDTO"}},"number":{"type":"integer","format":"int32"},"sort":{"$ref":"#/components/schemas/SortObject"},"numberOfElements":{"type":"integer","format":"int32"},"first":{"type":"boolean"},"last":{"type":"boolean"},"empty":{"type":"boolean"}}},"PageableObject":{"type":"object","properties":{"paged":{"type":"boolean"},"pageNumber":{"type":"integer","format":"int32"},"pageSize":{"type":"integer","format":"int32"},"offset":{"type":"integer","format":"int64"},"sort":{"$ref":"#/components/schemas/SortObject"},"unpaged":{"type":"boolean"}}},"ProjectSimpleDTO":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"code":{"type":"string"},"isActive":{"type":"boolean"}}},"SortObject":{"type":"object","properties":{"sorted":{"type":"boolean"},"empty":{"type":"boolean"},"unsorted":{"type":"boolean"}}},"TicketDTO":{"type":"object","properties":{"id":{"type":"integer","format":"int64"},"title":{"type":"string"},"description":{"type":"string"},"notes":{"type":"string"},"priority":{"type":"string","enum":["LOW","MEDIUM","HIGH","URGENT"]},"status":{"type":"string","enum":["OPEN","IN_PROGRESS","PENDING_CLIENT","PENDING_THIRD_PARTY","RESOLVED","CLOSED","REOPENED"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"resolvedAt":{"type":"string","format":"date-time"},"sourceType":{"type":"string","enum":["EMAIL","WEB_FORM","PHONE","CHAT","API","SYSTALINK_MARKETPLACE","INTERNAL"]},"sourceReference":{"type":"string"},"clientId":{"type":"integer","format":"int64"},"clientFirstName":{"type":"string"},"clientLastName":{"type":"string"},"clientEmail":{"type":"string"},"clientCompany":{"type":"string"},"assignedTo":{"$ref":"#/components/schemas/UserSimpleDTO"},"tags":{"type":"array","items":{"type":"string"}},"messageCount":{"type":"integer","format":"int32"},"project":{"$ref":"#/components/schemas/ProjectSimpleDTO"}}},"PageTicket":{"type":"object","properties":{"totalElements":{"type":"integer","format":"int64"},"totalPages":{"type":"integer","format":"int32"},"pageable":{"$ref":"#/components/schemas/PageableObject"},"size":{"type":"integer","format":"int32"},"content":{"type":"array","items":{"$ref":"#/components/schemas/Ticket"}},"number":{"type":"integer","format":"int32"},"sort":{"$ref":"#/components/schemas/SortObject"},"numberOfElements":{"type":"integer","format":"int32"},"first":{"type":"boolean"},"last":{"type":"boolean"},"empty":{"type":"boolean"}}},"TicketStatsResponse":{"type":"object","properties":{"statusCounts":{"type":"object","additionalProperties":{"type":"integer","format":"int64"}}}},"UnreadCountDTO":{"type":"object","properties":{"count":{"type":"integer","format":"int64"}}},"NotificationStatsDTO":{"type":"object","properties":{"total":{"type":"integer","format":"int64"},"unread":{"type":"integer","format":"int64"},"byType":{"type":"object","additionalProperties":{"type":"integer","format":"int64"}},"byPriority":{"type":"object","additionalProperties":{"type":"integer","format":"int64"}}}},"KnowledgeStatsDTO":{"type":"object","properties":{"totalArticles":{"type":"integer","format":"int32"},"publishedArticles":{"type":"integer","format":"int32"},"draftArticles":{"type":"integer","format":"int32"},"totalViews":{"type":"integer","format":"int32"},"topCategories":{"type":"array","items":{"$ref":"#/components/schemas/TopCategoryDTO"}}}},"TopCategoryDTO":{"type":"object","properties":{"category":{"type":"string","enum":["TECHNICAL","PROCESS","TROUBLESHOOTING","FAQ","BEST_PRACTICES","ESCALATION"]},"categoryName":{"type":"string"},"count":{"type":"integer","format":"int64"}}},"PageKnowledgeArticleDTO":{"type":"object","properties":{"totalElements":{"type":"integer","format":"int64"},"totalPages":{"type":"integer","format":"int32"},"pageable":{"$ref":"#/components/schemas/PageableObject"},"size":{"type":"integer","format":"int32"},"content":{"type":"array","items":{"$ref":"#/components/schemas/KnowledgeArticleDTO"}},"number":{"type":"integer","format":"int32"},"sort":{"$ref":"#/components/schemas/SortObject"},"numberOfElements":{"type":"integer","format":"int32"},"first":{"type":"boolean"},"last":{"type":"boolean"},"empty":{"type":"boolean"}}}},"securitySchemes":{"bearerAuth":{"type":"http","description":"### 🔑 Authentification JWT\n\n**Comment obtenir un token :**\n1. Utilisez l'endpoint `POST /api/auth/login`\n2. Fournissez email et mot de passe\n3. Récupérez le token dans la réponse\n4. Utilisez-le dans le header : `Authorization: Bearer <token>`\n\n**Rôles disponibles :**\n- `ADMIN` : Accès complet\n- `DEV` : Tickets techniques\n- `OPERATIONS` : Infrastructure\n- `SECURITY` : Sécurité\n- `SALES` : Commercial\n- `CLIENT` : Ses propres tickets\n","scheme":"bearer","bearerFormat":"JWT"},"marketplace-token":{"type":"apiKey","description":"### 🏪 Token Marketplace\n\n**Format :** Token Base64 contenant l'email du client\n\n**Utilisation :**\n```\nX-Marketplace-Token: <base64-encoded-email>\n```\n\n**Endpoints concernés :**\n- `/api/external/**`\n- Création de tickets externes\n- Consultation de statut\n","name":"X-Marketplace-Token","in":"header"}}}}