{
    "openapi": "3.0.0",
    "info": {
        "title": "Simpl\u00e9tudeApp \u2014 API REST",
        "description": "API Symfony 7 de gestion des cours de soutien scolaire. Authentification via JWT Bearer token (obtenu sur POST /api/auth/login).\n",
        "version": "2.0.0"
    },
    "paths": {
        "/api/auth/login": {
            "post": {
                "tags": [
                    "Auth",
                    "Login Check"
                ],
                "summary": "Connexion \u2014 obtenir un token JWT",
                "description": "Envoie les identifiants en JSON, re\u00e7oit un token JWT \u00e0 utiliser dans le header Authorization: Bearer <token> pour toutes les routes prot\u00e9g\u00e9es.\n",
                "operationId": "login_check_post",
                "requestBody": {
                    "description": "The login data",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "email",
                                    "password"
                                ],
                                "properties": {
                                    "email": {
                                        "type": "string",
                                        "format": "email",
                                        "example": "admin@simple-etude.com",
                                        "nullable": false
                                    },
                                    "password": {
                                        "type": "string",
                                        "example": "MonMotDePasse123",
                                        "nullable": false
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Token JWT retourn\u00e9",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "required": [
                                        "token"
                                    ],
                                    "properties": {
                                        "token": {
                                            "type": "string",
                                            "readOnly": true,
                                            "example": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...",
                                            "nullable": false
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Identifiants invalides"
                    }
                }
            }
        },
        "/api/admin/users/deleted": {
            "get": {
                "tags": [
                    "Admin"
                ],
                "summary": "GET /api/admin/users/deleted\nListe des snapshots utilisateurs supprim\u00e9s \u2014 r\u00e9serv\u00e9 au ROLE_SUPER_ADMIN.",
                "operationId": "get_admin_user_deleted_list",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/users/deleted/{id}": {
            "delete": {
                "tags": [
                    "Admin"
                ],
                "summary": "DELETE /api/admin/users/deleted/{id}\nPurge d\u00e9finitive d'un snapshot \u2014 r\u00e9serv\u00e9 au ROLE_SUPER_ADMIN.",
                "operationId": "delete_admin_user_deleted_purge",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "pattern": "\\d+"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/agenda": {
            "get": {
                "tags": [
                    "Admin Agenda"
                ],
                "summary": "GET /api/admin/agenda\nListe des professeurs actifs avec nb cr\u00e9neaux et indisponibilit\u00e9s \u00e0 venir.",
                "operationId": "get_admin_agenda_list",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/agenda/{id}": {
            "get": {
                "tags": [
                    "Admin Agenda"
                ],
                "summary": "GET /api/admin/agenda/{id}\nD\u00e9tail : cr\u00e9neaux hebdomadaires + indisponibilit\u00e9s (d\u00e9croissant).",
                "operationId": "get_admin_agenda_teacher",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/candidatures": {
            "get": {
                "tags": [
                    "Admin"
                ],
                "summary": "GET /api/admin/candidatures\nListe toutes les candidatures (pending en premier).",
                "operationId": "get_admin_candidatures_list",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/candidatures/{id}/valider": {
            "patch": {
                "tags": [
                    "Admin"
                ],
                "summary": "PATCH /api/admin/candidatures/{id}/valider\nValide une candidature :\n- Assigne le prof \u00e0 la session\n- Passe la demande en \"assigned\"\n- Rejette les autres candidatures pending pour la m\u00eame demande\n- Envoie les emails au prof et au parent",
                "operationId": "patch_admin_candidature_valider",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/candidatures/{id}/rejeter": {
            "patch": {
                "tags": [
                    "Admin"
                ],
                "summary": "PATCH /api/admin/candidatures/{id}/rejeter",
                "operationId": "patch_admin_candidature_rejeter",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/enfants": {
            "get": {
                "tags": [
                    "Admin"
                ],
                "summary": "GET /api/admin/enfants\nListe tous les enfants avec leurs parents et leurs contrats.",
                "operationId": "get_admin_enfants_list",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/dashboard/static": {
            "get": {
                "tags": [
                    "Admin"
                ],
                "summary": "GET /api/admin/dashboard/static",
                "description": "Donn\u00e9es permanentes (aucun filtre) :\n- KPIs courants\n- Alertes (actions requises)\n- \u00c9l\u00e8ves par niveau scolaire\n- Statuts contrats parents (tous)\n- Statuts profils professeurs (candidatures pro)",
                "operationId": "get_admin_dashboard_static",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/dashboard/filtered": {
            "get": {
                "tags": [
                    "Admin"
                ],
                "summary": "GET /api/admin/dashboard/filtered?year=2026&month=06",
                "description": "Donn\u00e9es filtrables par p\u00e9riode :\n- Cours par mati\u00e8re\n- Flux des cours (statuts)\n- Top professeurs (sessions compl\u00e9t\u00e9es)\n- \u00c9volution des inscriptions (12 mois de l'ann\u00e9e cibl\u00e9e)\n\nyear  = YYYY | 'all'\nmonth = MM   | 'all'  (ignor\u00e9 si year = 'all')",
                "operationId": "get_admin_dashboard_filtered",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/mailing/campaign": {
            "post": {
                "tags": [
                    "Mailing"
                ],
                "summary": "POST /api/admin/mailing/campaign\nBody JSON : { from, roles[], subject, content }",
                "operationId": "post_admin_mailing_campaign",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/mailing/history": {
            "get": {
                "tags": [
                    "Mailing"
                ],
                "summary": "GET /api/admin/mailing/history\n30 derni\u00e8res campagnes envoy\u00e9es, ordre ant\u00e9chronologique.",
                "operationId": "get_admin_mailing_history",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/mailing/newsletter/count": {
            "get": {
                "tags": [
                    "Mailing"
                ],
                "summary": "GET /api/admin/mailing/newsletter/count\nNombre d'abonn\u00e9s newsletter actifs.",
                "operationId": "get_admin_mailing_newsletter_count",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/mailing/newsletter": {
            "post": {
                "tags": [
                    "Mailing"
                ],
                "summary": "POST /api/admin/mailing/newsletter\nBody JSON : { from, subject, content }\nEnvoie la campagne \u00e0 tous les abonn\u00e9s newsletter.",
                "operationId": "post_admin_mailing_newsletter",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/map-users": {
            "get": {
                "tags": [
                    "Admin"
                ],
                "summary": "GET /api/admin/map-users",
                "description": "Retourne tous les parents et professeurs actifs avec :\n- coordonn\u00e9es GPS de leur adresse par d\u00e9faut (null si aucune)\n- statut contractuel\n- date du dernier cours effectu\u00e9",
                "operationId": "get_admin_map_users",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/parents/{uuid}": {
            "get": {
                "tags": [
                    "Admin"
                ],
                "summary": "GET /api/admin/parents/{uuid}\nD\u00e9tail parent : enfants li\u00e9s + adresse par d\u00e9faut.",
                "operationId": "get_api_admin_parent_detail",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/parents/{uuid}/addresses": {
            "get": {
                "tags": [
                    "Admin"
                ],
                "summary": "GET /api/admin/parents/{uuid}/addresses\nListe toutes les adresses du profil parent.",
                "operationId": "get_api_admin_parent_list_addresses",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            },
            "post": {
                "tags": [
                    "Admin"
                ],
                "summary": "POST /api/admin/parents/{uuid}/addresses\nAjoute une adresse au profil parent.",
                "description": "Body : { label?, street, streetComplement?, postalCode, city, latitude?, longitude?, isDefault? }",
                "operationId": "post_api_admin_parent_add_address",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/parents/{uuid}/addresses/{id}/default": {
            "patch": {
                "tags": [
                    "Admin"
                ],
                "summary": "PATCH /api/admin/parents/{uuid}/addresses/{id}/default\nD\u00e9finit une adresse comme adresse par d\u00e9faut.",
                "operationId": "patch_api_admin_parent_set_address_default",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/parents/{uuid}/children/{childProfileId}": {
            "patch": {
                "tags": [
                    "Admin"
                ],
                "summary": "PATCH /api/admin/parents/{uuid}/children/{childProfileId}\nMet \u00e0 jour les infos d'un enfant (niveau scolaire, classe, etc.).",
                "description": "Body : { firstName?, lastName?, birthDate?, schoolLevel?, schoolClass?, specialNeeds?, relationship? }",
                "operationId": "patch_api_admin_parent_update_child",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "childProfileId",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/parents/{uuid}/child": {
            "post": {
                "tags": [
                    "Admin"
                ],
                "summary": "POST /api/admin/parents/{uuid}/child\nCr\u00e9er et lier un enfant au profil parent.",
                "description": "Body : { firstName, lastName, birthDate?, schoolLevel?, schoolClass?, specialNeeds?, relationship? }",
                "operationId": "post_api_admin_parent_add_child",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/referrals/stats": {
            "get": {
                "tags": [
                    "Admin"
                ],
                "summary": "GET /api/admin/referrals/stats\nKPIs globaux pour la page admin parrainage.",
                "operationId": "get_admin_referral_stats",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/referrals/codes": {
            "get": {
                "tags": [
                    "Admin"
                ],
                "summary": "GET /api/admin/referrals/codes\nListe tous les codes de parrainage avec leurs stats.",
                "operationId": "get_admin_referral_codes_list",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/referrals/codes/{id}/toggle": {
            "patch": {
                "tags": [
                    "Admin"
                ],
                "summary": "PATCH /api/admin/referrals/codes/{id}/toggle\nActive ou d\u00e9sactive un code.",
                "operationId": "patch_admin_referral_code_toggle",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/referrals/codes/{id}/expiry": {
            "patch": {
                "tags": [
                    "Admin"
                ],
                "summary": "PATCH /api/admin/referrals/codes/{id}/expiry\nModifie la date d'expiration d'un code (null pour supprimer l'expiration).",
                "description": "Body : { \"expiresAt\": \"2026-12-31\" | null }",
                "operationId": "patch_admin_referral_code_expiry",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/referrals/list": {
            "get": {
                "tags": [
                    "Admin"
                ],
                "summary": "GET /api/admin/referrals/list\nListe tous les parrainages, filtrables par statut.",
                "operationId": "get_admin_referral_list",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/referrals/{id}/validate": {
            "post": {
                "tags": [
                    "Admin"
                ],
                "summary": "POST /api/admin/referrals/{id}/validate\nValide un parrainage (cr\u00e9dite les heures).",
                "operationId": "post_admin_referral_validate",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/referrals/{id}/cancel": {
            "post": {
                "tags": [
                    "Admin"
                ],
                "summary": "POST /api/admin/referrals/{id}/cancel\nAnnule un parrainage (sans cr\u00e9diter d'heures).",
                "operationId": "post_admin_referral_cancel",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/school-levels/all": {
            "get": {
                "tags": [
                    "Admin"
                ],
                "summary": "GET /api/admin/school-levels/all \u2014 liste tous les niveaux pour tout le monde",
                "operationId": "get_api_admin_school_level_list_all",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/school-levels": {
            "get": {
                "tags": [
                    "Admin"
                ],
                "summary": "GET /api/admin/school-levels \u2014 liste tous les niveaux",
                "operationId": "get_api_admin_school_level_list",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            },
            "post": {
                "tags": [
                    "Admin"
                ],
                "summary": "POST /api/admin/school-levels \u2014 cr\u00e9er un niveau (admin uniquement)",
                "operationId": "post_api_admin_school_level_create",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/school-levels/{id}": {
            "patch": {
                "tags": [
                    "Admin"
                ],
                "summary": "PATCH /api/admin/school-levels/{id} \u2014 modifier nom, tarif, ordre",
                "operationId": "patch_api_admin_school_level_update",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/school-levels/{id}/toggle": {
            "patch": {
                "tags": [
                    "Admin"
                ],
                "summary": "PATCH /api/admin/school-levels/{id}/toggle \u2014 activer / d\u00e9sactiver",
                "operationId": "patch_api_admin_school_level_toggle",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/activities/teachers": {
            "get": {
                "tags": [
                    "Admin Stats"
                ],
                "summary": "GET /api/admin/activities/teachers?month=YYYY-MM\nProfesseurs ayant donn\u00e9 au moins un cours termin\u00e9 ce mois.",
                "operationId": "get_admin_activities_teachers",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/prestations/clients": {
            "get": {
                "tags": [
                    "Admin Stats"
                ],
                "summary": "GET /api/admin/prestations/clients?month=YYYY-MM\nClients (parents) ayant eu au moins un cours termin\u00e9 ce mois.",
                "operationId": "get_admin_prestations_clients",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/activities": {
            "get": {
                "tags": [
                    "Admin Stats"
                ],
                "summary": "GET /api/admin/activities?month=YYYY-MM\nStats mensuelles : nb cours et heures par groupe de niveau.",
                "operationId": "get_admin_activities",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/activities/{id}": {
            "get": {
                "tags": [
                    "Admin Stats"
                ],
                "summary": "GET /api/admin/activities/{id}?month=YYYY-MM\nSessions termin\u00e9es d'un prof sur un mois \u2014 pour la fiche de paiement.",
                "operationId": "get_admin_teacher_activities",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/prestations/{id}": {
            "get": {
                "tags": [
                    "Admin Stats"
                ],
                "summary": "GET /api/admin/prestations/{id}?month=YYYY-MM\nSessions termin\u00e9es pour les enfants d'un parent/client sur un mois \u2014 pour le relev\u00e9 de prestations.",
                "operationId": "get_admin_parent_prestations",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/subjects": {
            "get": {
                "operationId": "get_api_admin_subject_list",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            },
            "post": {
                "tags": [
                    "R\u00e9f\u00e9rentiels"
                ],
                "summary": "POST /api/admin/subjects\nCr\u00e9er une nouvelle mati\u00e8re.",
                "description": "Body : { name, color? }",
                "operationId": "post_api_admin_subject_create",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/subjects/{id}": {
            "delete": {
                "tags": [
                    "R\u00e9f\u00e9rentiels"
                ],
                "summary": "DELETE /api/admin/subjects/{id}\nD\u00e9sactiver une mati\u00e8re (soft delete \u2014 ne supprime pas en BDD).",
                "description": "Les cours existants r\u00e9f\u00e9ren\u00e7ant cette mati\u00e8re ne sont pas affect\u00e9s.",
                "operationId": "delete_api_admin_subject_toggle",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            },
            "patch": {
                "tags": [
                    "R\u00e9f\u00e9rentiels"
                ],
                "summary": "PATCH /api/admin/subjects/{id}\nModifier une mati\u00e8re (nom, couleur).",
                "description": "Body : { name?, color? }",
                "operationId": "patch_api_admin_subject_update",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/teachers/{uuid}": {
            "get": {
                "tags": [
                    "Admin"
                ],
                "summary": "GET /api/admin/teachers/{uuid}\nD\u00e9tail enseignant : mati\u00e8res + note moyenne + r\u00e9sum\u00e9.",
                "operationId": "get_api_admin_teacher_detail",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/teachers/{uuid}/subjects": {
            "patch": {
                "tags": [
                    "Admin"
                ],
                "summary": "PATCH /api/admin/teachers/{uuid}/subjects\nRemplace la liste compl\u00e8te des mati\u00e8res enseign\u00e9es.",
                "description": "Body : { subjects: [{ subjectId: int, maxLevel?: string }] }",
                "operationId": "patch_api_admin_teacher_set_subjects",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/teachers/{uuid}/profile-status": {
            "patch": {
                "tags": [
                    "Admin"
                ],
                "summary": "PATCH /api/admin/teachers/{uuid}/profile-status\nChange le statut du TeacherProfile (pas du compte User).",
                "description": "Body : { status: 'active'|'inactive'|'suspended'|'pending' }",
                "operationId": "patch_api_admin_teacher_profile_status",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/teachers/{uuid}/teacher-info": {
            "patch": {
                "tags": [
                    "Admin"
                ],
                "summary": "PATCH /api/admin/teachers/{uuid}/teacher-info\nModifie la bio et/ou le rayon de d\u00e9placement du professeur (c\u00f4t\u00e9 admin).",
                "description": "Body (tous optionnels) : bio, travelRadiusKm",
                "operationId": "patch_api_admin_teacher_update_info",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/teachers/{uuid}/reviews": {
            "get": {
                "tags": [
                    "Admin"
                ],
                "summary": "GET /api/admin/teachers/{uuid}/reviews\nListe des avis laiss\u00e9s pour ce professeur.",
                "operationId": "get_api_admin_teacher_reviews",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/teachers/{uuid}/addresses": {
            "get": {
                "tags": [
                    "Admin"
                ],
                "operationId": "get_api_admin_teacher_list_addresses",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            },
            "post": {
                "tags": [
                    "Admin"
                ],
                "operationId": "post_api_admin_teacher_add_address",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/teachers/{uuid}/addresses/{id}/default": {
            "patch": {
                "tags": [
                    "Admin"
                ],
                "operationId": "patch_api_admin_teacher_set_address_default",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/users": {
            "get": {
                "tags": [
                    "Admin"
                ],
                "summary": "GET /api/admin/users\nListe tous les utilisateurs. Filtres optionnels : ?role= &active=1",
                "operationId": "get_admin_user_list",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            },
            "post": {
                "tags": [
                    "Admin"
                ],
                "summary": "POST /api/admin/users\nCr\u00e9er un compte (admin cr\u00e9e un compte pour quelqu'un).",
                "description": "Body : { email, roles, password? }\nSi aucun mot de passe fourni, g\u00e9n\u00e8re un temporaire (l'user devra le changer).",
                "operationId": "post_admin_user_create",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/users/{uuid}": {
            "get": {
                "tags": [
                    "Admin"
                ],
                "summary": "GET /api/admin/users/{uuid}\nD\u00e9tail d'un utilisateur.",
                "operationId": "get_admin_user_detail",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            },
            "delete": {
                "tags": [
                    "Admin"
                ],
                "summary": "DELETE /api/admin/users/{uuid}\nSuppression d\u00e9finitive \u2014 r\u00e9serv\u00e9 au ROLE_SUPER_ADMIN.",
                "description": "Snapshot cr\u00e9\u00e9, tous les fichiers physiques supprim\u00e9s, relations nettoy\u00e9es.",
                "operationId": "delete_admin_user_delete",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/users/{uuid}/status": {
            "patch": {
                "tags": [
                    "Admin"
                ],
                "summary": "PATCH /api/admin/users/{uuid}/status\nActiver ou d\u00e9sactiver un compte.",
                "description": "Body : { isActive: true|false }",
                "operationId": "patch_admin_user_status",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/users/{uuid}/info": {
            "patch": {
                "tags": [
                    "Admin"
                ],
                "summary": "PATCH /api/admin/users/{uuid}/info\nModifier les informations de base : pr\u00e9nom, nom, email, t\u00e9l\u00e9phone.",
                "description": "Body : { firstName?, lastName?, email?, phone? }",
                "operationId": "patch_admin_user_info",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/users/{uuid}/roles": {
            "patch": {
                "tags": [
                    "Admin"
                ],
                "summary": "PATCH /api/admin/users/{uuid}/roles\nModifier les r\u00f4les d'un utilisateur.",
                "description": "Body : { roles: [\"ROLE_PARENT\", \"ROLE_USER\"] }",
                "operationId": "patch_admin_user_roles",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/users/{uuid}/password": {
            "patch": {
                "tags": [
                    "Admin"
                ],
                "summary": "PATCH /api/admin/users/{uuid}/password\nR\u00e9initialiser le mot de passe d'un utilisateur (par un admin).",
                "description": "Body : { password, forceChange? }          \u2014 mode manuel\n| { autoGenerate: true }              \u2014 g\u00e9n\u00e9ration automatique (force toujours isFirstLogin)",
                "operationId": "patch_admin_user_password",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/users/{uuid}/role": {
            "patch": {
                "tags": [
                    "Admin"
                ],
                "summary": "PATCH /api/admin/users/{uuid}/role\nAffecte UN r\u00f4le fonctionnel en respectant la r\u00e8gle d'exclusivit\u00e9.",
                "description": "TEACHER, PARENT, INTERNE, STUDENT ne peuvent pas cohabiter.\nBody : { \"role\": \"ROLE_TEACHER\" }",
                "operationId": "patch_admin_user_set_role",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/users/{uuid}/documents": {
            "get": {
                "tags": [
                    "Admin"
                ],
                "summary": "GET /api/admin/users/{uuid}/documents\nDocuments d'un utilisateur : personnels + candidature (prof).",
                "operationId": "get_admin_user_documents",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/auth/request-email-change": {
            "post": {
                "tags": [
                    "Authentification"
                ],
                "summary": "POST /api/auth/request-email-change",
                "description": "Body : { \"newEmail\": \"...\", \"currentPassword\": \"...\" }\n\nValide le mot de passe, v\u00e9rifie que l'email n'est pas d\u00e9j\u00e0 pris,\ng\u00e9n\u00e8re un code \u00e0 6 chiffres et l'envoie sur le NOUVEL email.",
                "operationId": "post_auth_request_email_change",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/auth/confirm-email-change": {
            "post": {
                "tags": [
                    "Authentification"
                ],
                "summary": "POST /api/auth/confirm-email-change",
                "description": "Body : { \"code\": \"123456\" }\n\nValide le code et applique le changement d'email.",
                "operationId": "post_auth_confirm_email_change",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/auth/change-password": {
            "patch": {
                "tags": [
                    "Authentification"
                ],
                "summary": "PATCH /api/auth/change-password",
                "description": "Body requis :\n  newPassword     : string\n  confirmPassword : string\n\nBody requis si isFirstLogin = false :\n  currentPassword : string",
                "operationId": "patch_auth_change_password",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/auth/forgot-password": {
            "post": {
                "tags": [
                    "Auth"
                ],
                "summary": "\u00c9tape 1 \u2014 Demande de r\u00e9initialisation du mot de passe.",
                "description": "POST /api/auth/forgot-password\nBody : { \"email\": \"user@example.com\" }\n\nRetourne toujours un succ\u00e8s (m\u00eame si le compte n'existe pas)\npour ne pas r\u00e9v\u00e9ler quels emails sont enregistr\u00e9s.",
                "operationId": "post_auth_forgot_password",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/auth/forgot-password/verify": {
            "post": {
                "tags": [
                    "Auth"
                ],
                "summary": "\u00c9tape 2 \u2014 V\u00e9rification du code de r\u00e9initialisation.",
                "description": "POST /api/auth/forgot-password/verify\nBody : { \"email\": \"user@example.com\", \"code\": \"123456\" }",
                "operationId": "post_auth_forgot_password_verify",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/auth/forgot-password/reset": {
            "post": {
                "tags": [
                    "Auth"
                ],
                "summary": "\u00c9tape 3 \u2014 Enregistrement du nouveau mot de passe.",
                "description": "POST /api/auth/forgot-password/reset\nBody : { \"email\": \"user@example.com\", \"password\": \"...\", \"confirmPassword\": \"...\" }",
                "operationId": "post_auth_forgot_password_reset",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/auth/pending-reviews": {
            "get": {
                "tags": [
                    "Auth"
                ],
                "summary": "GET /api/auth/pending-reviews",
                "description": "Prof  : sessions completed apr\u00e8s le 01/07/2026 (Juillet) sans LessonReport d\u00e9pos\u00e9.\nParent: sessions completed apr\u00e8s le 01/07/2026 sans LessonReview laiss\u00e9.",
                "operationId": "get_auth_pending_reviews",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/auth/me": {
            "get": {
                "tags": [
                    "Auth"
                ],
                "summary": "GET /api/auth/me\nRetourne les informations de l'utilisateur actuellement connect\u00e9.",
                "description": "Prot\u00e9g\u00e9 par JWT (firewall api dans security.yaml).",
                "operationId": "get_auth_me",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/auth/register": {
            "post": {
                "tags": [
                    "Auth"
                ],
                "summary": "\u00c9tape 1 \u2014 Envoi du code de v\u00e9rification par email.",
                "description": "POST /api/auth/register\nBody : { \"email\": \"user@example.com\" }",
                "operationId": "post_auth_register",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/auth/register/verify": {
            "post": {
                "tags": [
                    "Auth"
                ],
                "summary": "\u00c9tape 2 \u2014 V\u00e9rification du code re\u00e7u par email.",
                "description": "POST /api/auth/register/verify\nBody : { \"email\": \"user@example.com\", \"code\": \"123456\" }",
                "operationId": "post_auth_register_verify",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/auth/register/activate": {
            "post": {
                "tags": [
                    "Auth"
                ],
                "summary": "\u00c9tape 3 \u2014 Cr\u00e9ation du compte avec mot de passe.",
                "description": "POST /api/auth/register/activate\nBody : { \"email\": \"user@example.com\", \"password\": \"...\", \"confirmPassword\": \"...\" }",
                "operationId": "post_auth_register_activate",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/availability/weekly": {
            "get": {
                "tags": [
                    "Disponibilit\u00e9s"
                ],
                "summary": "GET /api/availability/weekly\nR\u00e9cup\u00e8re les cr\u00e9neaux r\u00e9currents du prof connect\u00e9.",
                "operationId": "get_availability_weekly_list",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            },
            "post": {
                "tags": [
                    "Disponibilit\u00e9s"
                ],
                "summary": "POST /api/availability/weekly\nAjouter un cr\u00e9neau r\u00e9current.",
                "description": "Body : { dayOfWeek: 1-7, startTime: \"09:00\", endTime: \"12:00\" }\ndayOfWeek : 1=Lundi, 7=Dimanche",
                "operationId": "post_availability_weekly_create",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/availability/weekly/{id}": {
            "put": {
                "tags": [
                    "Disponibilit\u00e9s"
                ],
                "summary": "PUT /api/availability/weekly/{id}\nModifier un cr\u00e9neau r\u00e9current.",
                "operationId": "put_availability_weekly_update",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            },
            "delete": {
                "tags": [
                    "Disponibilit\u00e9s"
                ],
                "summary": "DELETE /api/availability/weekly/{id}\nSupprimer un cr\u00e9neau r\u00e9current.",
                "operationId": "delete_availability_weekly_delete",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/availability/unavailabilities": {
            "get": {
                "tags": [
                    "Disponibilit\u00e9s"
                ],
                "summary": "GET /api/availability/unavailabilities\nListe les indisponibilit\u00e9s du prof connect\u00e9.",
                "operationId": "get_availability_unavailabilities_list",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            },
            "post": {
                "tags": [
                    "Disponibilit\u00e9s"
                ],
                "summary": "POST /api/availability/unavailabilities\nD\u00e9clarer une indisponibilit\u00e9 ponctuelle.",
                "description": "Body : { startDatetime: \"2025-12-24T00:00:00\", endDatetime: \"2025-12-26T23:59:59\", reason: \"Cong\u00e9s\" }",
                "operationId": "post_availability_unavailabilities_create",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/availability/unavailabilities/{id}": {
            "delete": {
                "tags": [
                    "Disponibilit\u00e9s"
                ],
                "summary": "DELETE /api/availability/unavailabilities/{id}\nSupprimer une indisponibilit\u00e9.",
                "operationId": "delete_availability_unavailabilities_delete",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/availability/teacher/{uuid}": {
            "get": {
                "tags": [
                    "Disponibilit\u00e9s"
                ],
                "summary": "GET /api/availability/teacher/{uuid}\nCr\u00e9neaux r\u00e9currents d'un prof \u2014 visible par les parents et admins.",
                "operationId": "get_availability_teacher_public",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/contact": {
            "post": {
                "tags": [
                    "Contact"
                ],
                "summary": "POST /api/contact\nFormulaire public de contact (visiteurs du site).",
                "description": "Body : { name, email, subject, message }",
                "operationId": "post_contact_public",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/aide-contact": {
            "post": {
                "tags": [
                    "Contact"
                ],
                "summary": "POST /api/aide-contact\nFormulaire d'aide interne \u2014 route vers le bon service.",
                "description": "Body : { subject, message, service?, serviceName? }\nL'email de l'utilisateur est r\u00e9cup\u00e9r\u00e9 depuis le JWT.",
                "operationId": "post_contact_support",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/testimonials": {
            "get": {
                "tags": [
                    "T\u00e9moignages"
                ],
                "operationId": "get_public_testimonial_list",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/testimonials/submit": {
            "post": {
                "tags": [
                    "T\u00e9moignages"
                ],
                "operationId": "post_public_testimonial_submit",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/testimonials": {
            "get": {
                "tags": [
                    "T\u00e9moignages"
                ],
                "operationId": "get_admin_testimonial_list",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            },
            "post": {
                "tags": [
                    "T\u00e9moignages"
                ],
                "operationId": "post_admin_testimonial_create",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/testimonials/{uuid}": {
            "delete": {
                "tags": [
                    "T\u00e9moignages"
                ],
                "operationId": "delete_admin_testimonial_delete",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            },
            "patch": {
                "tags": [
                    "T\u00e9moignages"
                ],
                "operationId": "patch_admin_testimonial_update",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/testimonials/{uuid}/photo": {
            "post": {
                "tags": [
                    "T\u00e9moignages"
                ],
                "operationId": "post_admin_testimonial_photo",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/testimonials/{uuid}/token": {
            "post": {
                "tags": [
                    "T\u00e9moignages"
                ],
                "operationId": "post_admin_testimonial_generate_token",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/contracts": {
            "get": {
                "tags": [
                    "Contrats"
                ],
                "summary": "GET /api/contracts\nParent : ses propres contrats.",
                "description": "Admin : tous les contrats (filtre optionnel ?status=active).",
                "operationId": "get_contract_list",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/contracts/has-valid": {
            "get": {
                "tags": [
                    "Contrats"
                ],
                "summary": "GET /api/contracts/has-valid\nV\u00e9rifie si le parent connect\u00e9 poss\u00e8de un contrat actif.",
                "description": "Utilis\u00e9 par le front pour conditionner l'acc\u00e8s \u00e0 la commande de cours.",
                "operationId": "get_contract_has_valid",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/contracts/{uuid}": {
            "get": {
                "tags": [
                    "Contrats"
                ],
                "summary": "GET /api/contracts/{uuid}\nD\u00e9tail d'un contrat. Un parent ne peut voir que ses propres contrats.",
                "operationId": "get_contract_detail",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/contracts/{uuid}/signature": {
            "get": {
                "tags": [
                    "Contrats"
                ],
                "summary": "GET /api/contracts/{uuid}/signature\nT\u00e9l\u00e9charger le fichier de signature du contrat.",
                "description": "Un parent ne peut acc\u00e9der qu'\u00e0 ses propres contrats.",
                "operationId": "get_contract_signature_download",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/contracts/{uuid}/sign": {
            "post": {
                "tags": [
                    "Contrats"
                ],
                "summary": "PATCH /api/contracts/{uuid}/sign\nLe parent enregistre sa signature sur le contrat.",
                "description": "FormData : file (image PNG de la signature)\n\u2192 signedAt renseign\u00e9, signatureFile sauvegard\u00e9, status \u2192 active",
                "operationId": "post_contract_sign",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            },
            "patch": {
                "tags": [
                    "Contrats"
                ],
                "summary": "PATCH /api/contracts/{uuid}/sign\nLe parent enregistre sa signature sur le contrat.",
                "description": "FormData : file (image PNG de la signature)\n\u2192 signedAt renseign\u00e9, signatureFile sauvegard\u00e9, status \u2192 active",
                "operationId": "patch_contract_sign",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/contracts/{uuid}/pdf": {
            "get": {
                "tags": [
                    "Contrats"
                ],
                "summary": "GET /api/contracts/{uuid}/pdf\nG\u00e9n\u00e8re et t\u00e9l\u00e9charge le PDF du contrat parent.",
                "operationId": "get_contract_pdf",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/contracts": {
            "post": {
                "tags": [
                    "Contrats"
                ],
                "summary": "POST /api/admin/contracts\nCr\u00e9e un contrat parent (admin).",
                "description": "Body : { parentProfileId, startDate, contractType, endDate?, level?, schoolClass?, childProfileIds?, subjectIds? }",
                "operationId": "post_admin_contract_create",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/contracts/{uuid}/update": {
            "patch": {
                "tags": [
                    "Contrats"
                ],
                "summary": "PATCH /api/admin/contracts/{uuid}/update\nModifie un contrat parent.",
                "description": "Contrat sign\u00e9 : r\u00e9serv\u00e9 au ROLE_ADMIN_THAT_APP.",
                "operationId": "patch_admin_contract_update",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/contracts/{uuid}/approve": {
            "patch": {
                "tags": [
                    "Contrats"
                ],
                "summary": "PATCH /api/admin/contracts/{uuid}/approve\nL'admin approuve le contrat \u2192 status passe \u00e0 'active'.",
                "operationId": "patch_admin_contract_approve",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/contracts/{uuid}/terminate": {
            "patch": {
                "tags": [
                    "Contrats"
                ],
                "summary": "PATCH /api/admin/contracts/{uuid}/terminate\nL'admin r\u00e9silie le contrat.",
                "description": "Body : { \"reason\": \"...\" }",
                "operationId": "patch_admin_contract_terminate",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/teacher-contracts": {
            "get": {
                "tags": [
                    "TeacherContrats"
                ],
                "summary": "GET /api/teacher-contracts\nRetourne les contrats du professeur connect\u00e9.",
                "operationId": "get_teacher_contract_list",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/teacher-contracts/{id}": {
            "get": {
                "tags": [
                    "TeacherContrats"
                ],
                "summary": "GET /api/teacher-contracts/{id}\nD\u00e9tail d'un contrat. Un professeur ne peut voir que les siens.",
                "operationId": "get_teacher_contract_show",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/teacher-contracts/{id}/sign": {
            "post": {
                "tags": [
                    "TeacherContrats"
                ],
                "summary": "PATCH /api/teacher-contracts/{id}/sign\nLe professeur enregistre sa signature sur son contrat.",
                "description": "FormData : file (image PNG de la signature)\n\u2192 signedAt, signatureFile sauvegard\u00e9s, status \u2192 active",
                "operationId": "post_teacher_contract_sign",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            },
            "patch": {
                "tags": [
                    "TeacherContrats"
                ],
                "summary": "PATCH /api/teacher-contracts/{id}/sign\nLe professeur enregistre sa signature sur son contrat.",
                "description": "FormData : file (image PNG de la signature)\n\u2192 signedAt, signatureFile sauvegard\u00e9s, status \u2192 active",
                "operationId": "patch_teacher_contract_sign",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/teacher-contracts/{id}/pdf": {
            "get": {
                "tags": [
                    "TeacherContrats"
                ],
                "summary": "GET /api/teacher-contracts/{id}/pdf\nG\u00e9n\u00e8re et t\u00e9l\u00e9charge le PDF du contrat professeur.",
                "operationId": "get_teacher_contract_pdf",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/teacher-contracts": {
            "get": {
                "tags": [
                    "TeacherContrats"
                ],
                "summary": "GET /api/admin/teacher-contracts\nListe tous les contrats professeurs (admin).",
                "operationId": "get_admin_teacher_contract_list",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            },
            "post": {
                "tags": [
                    "TeacherContrats"
                ],
                "summary": "POST /api/admin/teacher-contracts\nCr\u00e9e un contrat pour un professeur (admin).",
                "description": "Body: { teacherProfileId, startDate, position?, hourlyRateCents?, siretNumber? }",
                "operationId": "post_admin_teacher_contract_create",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/teacher-contracts/{id}": {
            "get": {
                "tags": [
                    "TeacherContrats"
                ],
                "summary": "GET /api/admin/teacher-contracts/{id}\nD\u00e9tail d'un contrat professeur (admin, sans restriction de propri\u00e9t\u00e9).",
                "operationId": "get_admin_teacher_contract_show",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/teacher-contracts/{id}/approve": {
            "patch": {
                "tags": [
                    "TeacherContrats"
                ],
                "summary": "PATCH /api/admin/teacher-contracts/{id}/approve\nApprouve et active un contrat professeur.",
                "operationId": "patch_admin_teacher_contract_approve",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/teacher-contracts/{id}/terminate": {
            "patch": {
                "tags": [
                    "TeacherContrats"
                ],
                "summary": "PATCH /api/admin/teacher-contracts/{id}/terminate\nR\u00e9silie un contrat professeur.",
                "description": "Body: { reason }",
                "operationId": "patch_admin_teacher_contract_terminate",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/teacher-contracts/{id}/update": {
            "patch": {
                "tags": [
                    "TeacherContrats"
                ],
                "summary": "PATCH /api/admin/teacher-contracts/{id}/update\nModifie un contrat professeur.",
                "description": "Contrat sign\u00e9 : r\u00e9serv\u00e9 au ROLE_ADMIN_THAT_APP.",
                "operationId": "patch_admin_teacher_contract_update",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/teacher-contracts/{id}/signature": {
            "get": {
                "tags": [
                    "TeacherContrats"
                ],
                "summary": "GET /api/admin/teacher-contracts/{id}/signature\nT\u00e9l\u00e9charger le fichier de signature d'un contrat professeur (admin).",
                "operationId": "get_admin_teacher_contract_signature",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/documents": {
            "get": {
                "tags": [
                    "Documents"
                ],
                "summary": "GET /api/documents\nListe les documents personnels de l'utilisateur connect\u00e9.",
                "description": "Admin : peut voir les docs de n'importe qui via ?email=",
                "operationId": "get_document_list",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            },
            "post": {
                "tags": [
                    "Documents"
                ],
                "summary": "POST /api/documents\nUpload d'un document personnel.",
                "description": "FormData : file, type (id_card|passport|rib|address_proof|other)",
                "operationId": "post_document_upload",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/documents/{id}/download": {
            "get": {
                "tags": [
                    "Documents"
                ],
                "summary": "GET /api/documents/{id}/download\nT\u00e9l\u00e9charger un document. Le propri\u00e9taire ou un admin peut acc\u00e9der.",
                "operationId": "get_document_download",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/documents/{id}": {
            "delete": {
                "tags": [
                    "Documents"
                ],
                "summary": "DELETE /api/documents/{id}\nSupprimer un document. Le propri\u00e9taire ou un admin peut supprimer.",
                "operationId": "delete_document_delete",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/events": {
            "get": {
                "tags": [
                    "\u00c9v\u00e9nements"
                ],
                "operationId": "get_admin_event_list",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            },
            "post": {
                "tags": [
                    "\u00c9v\u00e9nements"
                ],
                "operationId": "post_admin_event_create",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/events/{uuid}": {
            "delete": {
                "tags": [
                    "\u00c9v\u00e9nements"
                ],
                "operationId": "delete_admin_event_delete",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            },
            "patch": {
                "tags": [
                    "\u00c9v\u00e9nements"
                ],
                "operationId": "patch_admin_event_update",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/events/{uuid}/image": {
            "post": {
                "tags": [
                    "\u00c9v\u00e9nements"
                ],
                "operationId": "post_admin_event_upload_image",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/events": {
            "get": {
                "tags": [
                    "\u00c9v\u00e9nements"
                ],
                "operationId": "get_public_event_list",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/formations": {
            "get": {
                "tags": [
                    "Formations"
                ],
                "operationId": "get_admin_formation_list",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            },
            "post": {
                "tags": [
                    "Formations"
                ],
                "operationId": "post_admin_formation_create",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/formations/{uuid}": {
            "delete": {
                "tags": [
                    "Formations"
                ],
                "operationId": "delete_admin_formation_delete",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            },
            "patch": {
                "tags": [
                    "Formations"
                ],
                "operationId": "patch_admin_formation_update",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/formations/{uuid}/image": {
            "post": {
                "tags": [
                    "Formations"
                ],
                "operationId": "post_admin_formation_image",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/formations/{uuid}": {
            "get": {
                "tags": [
                    "Formations"
                ],
                "operationId": "get_public_formation_show",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/formations": {
            "get": {
                "tags": [
                    "Formations"
                ],
                "operationId": "get_public_formation_list",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/leads": {
            "post": {
                "tags": [
                    "Leads"
                ],
                "summary": "POST /api/leads\nRoute publique \u2014 formulaire \"Prise d'informations\" accessible \u00e0 tous.",
                "operationId": "post_lead_create",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/leads": {
            "get": {
                "tags": [
                    "Leads"
                ],
                "summary": "GET /api/admin/leads\nListe tous les leads, filtrables par ?called=0|1.",
                "operationId": "get_admin_lead_list",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/leads/{id}/called": {
            "patch": {
                "tags": [
                    "Leads"
                ],
                "summary": "PATCH /api/admin/leads/{id}/called\nBascule le statut \"appel\u00e9\" d'un lead.",
                "description": "Body : { called: true|false }",
                "operationId": "patch_admin_lead_called",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/lesson-sessions/{uuid}/cancellation": {
            "get": {
                "tags": [
                    "Admin"
                ],
                "summary": "GET /api/admin/lesson-sessions/{uuid}/cancellation",
                "description": "Retourne le d\u00e9tail de l'annulation pour une session annul\u00e9e :\nqui a annul\u00e9 (prof / parent / admin), pourquoi, et si une p\u00e9nalit\u00e9 s'applique.",
                "operationId": "get_admin_lesson_cancellation_detail",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/lesson-reports/session/{sessionUuid}": {
            "get": {
                "tags": [
                    "Rapports"
                ],
                "summary": "GET /api/lesson-reports/session/{sessionUuid}",
                "description": "Retourne le rapport d'une session.\nAccessible par le prof de la session ou le parent concern\u00e9.",
                "operationId": "get_api_lesson_report_get",
                "parameters": [
                    {
                        "name": "sessionUuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            },
            "post": {
                "tags": [
                    "Rapports"
                ],
                "summary": "POST /api/lesson-reports/session/{sessionUuid}",
                "description": "Cr\u00e9e ou met \u00e0 jour le rapport p\u00e9dagogique du professeur pour une session.\nSeul le professeur assign\u00e9 \u00e0 la session peut soumettre un rapport.",
                "operationId": "post_api_lesson_report_submit",
                "parameters": [
                    {
                        "name": "sessionUuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/lesson-requests": {
            "get": {
                "tags": [
                    "Cours"
                ],
                "summary": "GET /api/lesson-requests\nAdmin   : toutes les demandes (filtre ?status= optionnel).",
                "description": "Prof    : les demandes dont il est le prof assign\u00e9 (via les sessions).\nParent  : ses propres demandes.",
                "operationId": "get_lesson_request_list",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            },
            "post": {
                "tags": [
                    "Cours"
                ],
                "summary": "POST /api/lesson-requests\nLe parent commande un cours pour son enfant.",
                "description": "Body requis :\n  childProfileId  : int    \u2014 ID de l'enfant (doit appartenir au parent)\n  subjectId       : int    \u2014 ID de la mati\u00e8re\n  durationMinutes : int    \u2014 dur\u00e9e souhait\u00e9e (60, 90, 120\u2026)\n\nBody optionnel :\n  requestedDate   : string \u2014 \"2025-11-20\"\n  requestedTime   : string \u2014 \"14:30\"\n  levelLabel      : string \u2014 niveau de l'\u00e9l\u00e8ve (d\u00e9normalis\u00e9, ex: \"Seconde\")\n  classLabel      : string \u2014 classe (ex: \"2nde B\")\n  notes           : string \u2014 instructions sp\u00e9ciales\n  customAddress   : string \u2014 adresse si diff\u00e9rente du domicile",
                "operationId": "post_lesson_request_create",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/lesson-requests/{uuid}": {
            "get": {
                "tags": [
                    "Cours"
                ],
                "summary": "GET /api/lesson-requests/{uuid}\nD\u00e9tail d'une demande. Parent : seulement la sienne.",
                "operationId": "get_lesson_request_detail",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/lesson-requests/{uuid}/cancel": {
            "patch": {
                "tags": [
                    "Cours"
                ],
                "summary": "PATCH /api/lesson-requests/{uuid}/cancel\nParent annule sa propre demande (uniquement si encore en pending).",
                "operationId": "patch_lesson_request_cancel",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/lesson-requests/unassigned": {
            "get": {
                "tags": [
                    "Cours"
                ],
                "summary": "GET /api/admin/lesson-requests/unassigned\nListe les demandes en attente d'un professeur.",
                "operationId": "get_admin_lesson_request_unassigned",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/lesson-requests": {
            "get": {
                "tags": [
                    "Cours"
                ],
                "summary": "GET /api/admin/lesson-requests\nToutes les demandes avec filtres.",
                "description": "Params optionnels : ?status= &childProfileId= &parentEmail=",
                "operationId": "get_admin_lesson_request_list",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/lesson-requests/{uuid}/assign": {
            "patch": {
                "tags": [
                    "Cours"
                ],
                "summary": "PATCH /api/admin/lesson-requests/{uuid}/assign\nL'admin assigne un professeur \u00e0 la session d\u00e9j\u00e0 cr\u00e9\u00e9e lors de la commande.",
                "description": "Body requis :\n  teacherProfileId : int    \u2014 ID du TeacherProfile\n\nBody optionnel :\n  scheduledDate    : string \u2014 \"2025-12-01\"  (si l'admin change la date convenue)\n  scheduledTime    : string \u2014 \"14:30\"        (si l'admin change l'heure convenue)",
                "operationId": "patch_admin_lesson_request_assign",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/lesson-requests/{uuid}/complete": {
            "patch": {
                "tags": [
                    "Cours"
                ],
                "summary": "PATCH /api/admin/lesson-requests/{uuid}/complete\nL'admin marque la demande comme compl\u00e9t\u00e9e.",
                "operationId": "patch_admin_lesson_request_complete",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/lesson-requests/{uuid}/nearby-teachers": {
            "get": {
                "tags": [
                    "Cours"
                ],
                "summary": "GET /api/admin/lesson-requests/{uuid}/nearby-teachers?radiusKm=20\nProfs actifs proches de l'adresse du parent, avec indicateur de disponibilit\u00e9.",
                "description": "Query params optionnels :\ncheckDate : string \"YYYY-MM-DD\" \u2014 surcharge la date pour le calcul de disponibilit\u00e9\ncheckTime : string \"HH:MM\"      \u2014 surcharge l'heure pour le calcul de disponibilit\u00e9",
                "operationId": "get_admin_lesson_request_nearby_teachers",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/lesson-requests/{uuid}": {
            "delete": {
                "tags": [
                    "Cours"
                ],
                "summary": "DELETE /api/admin/lesson-requests/{uuid}\nSupprime une commande uniquement si elle est encore en attente (pas de prof assign\u00e9).",
                "operationId": "delete_admin_lesson_request_delete",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/lesson-sessions": {
            "get": {
                "tags": [
                    "Cours"
                ],
                "summary": "GET /api/admin/lesson-sessions\nVue unifi\u00e9e : toutes les sessions (cr\u00e9\u00e9es depuis une commande OU depuis un pointage)\n+ les demandes en attente sans session planifi\u00e9e.",
                "description": "Tri\u00e9 par scheduledDate DESC, scheduledTime DESC (nulls en dernier).",
                "operationId": "get_admin_lesson_sessions_unified",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/lesson-reviews": {
            "post": {
                "tags": [
                    "Cours"
                ],
                "operationId": "post_lesson_review_create",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/lesson-reviews/session/{sessionUuid}": {
            "get": {
                "tags": [
                    "Cours"
                ],
                "operationId": "get_lesson_review_show",
                "parameters": [
                    {
                        "name": "sessionUuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            },
            "put": {
                "tags": [
                    "Cours"
                ],
                "operationId": "put_lesson_review_update",
                "parameters": [
                    {
                        "name": "sessionUuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            },
            "delete": {
                "tags": [
                    "Cours"
                ],
                "operationId": "delete_lesson_review_delete",
                "parameters": [
                    {
                        "name": "sessionUuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/lesson-reviews/teacher/{profileUuid}": {
            "get": {
                "tags": [
                    "Cours"
                ],
                "operationId": "get_lesson_review_teacher_rating",
                "parameters": [
                    {
                        "name": "profileUuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/lesson-sessions/my": {
            "get": {
                "tags": [
                    "Sessions"
                ],
                "operationId": "get_lesson_sessions_my",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/lesson-sessions/parent/pending-reschedules": {
            "get": {
                "tags": [
                    "Sessions"
                ],
                "operationId": "get_parent_pending_reschedules",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/lesson-sessions/{uuid}": {
            "get": {
                "tags": [
                    "Sessions"
                ],
                "operationId": "get_lesson_session_detail",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/lesson-sessions/{uuid}/cancel": {
            "patch": {
                "tags": [
                    "Sessions"
                ],
                "operationId": "patch_lesson_session_cancel",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/lesson-sessions/{uuid}/reschedule": {
            "post": {
                "tags": [
                    "Sessions"
                ],
                "operationId": "post_lesson_session_reschedule",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/lesson-sessions/{uuid}/reschedule/{rescheduleId}/respond": {
            "patch": {
                "tags": [
                    "Sessions"
                ],
                "operationId": "patch_lesson_session_reschedule_respond",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "rescheduleId",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/livret/teacher": {
            "get": {
                "tags": [
                    "Livret"
                ],
                "operationId": "get_livret_teacher",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/livret/parent": {
            "get": {
                "tags": [
                    "Livret"
                ],
                "operationId": "get_livret_parent",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/teacher/offres": {
            "get": {
                "tags": [
                    "Professeurs"
                ],
                "operationId": "get_teacher_offres_list",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/teacher/mes-candidatures": {
            "get": {
                "tags": [
                    "Professeurs"
                ],
                "summary": "GET /api/teacher/mes-candidatures\nHistorique de toutes les candidatures du prof connect\u00e9.",
                "operationId": "get_teacher_mes_candidatures",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/teacher/offres/{id}/postuler": {
            "post": {
                "tags": [
                    "Professeurs"
                ],
                "summary": "POST /api/teacher/offres/{id}/postuler\nLe prof postule sur une demande de cours.",
                "description": "Body JSON : { note?: string }",
                "operationId": "post_teacher_offres_apply",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/timesheets": {
            "get": {
                "tags": [
                    "Pointage"
                ],
                "summary": "GET /api/timesheets\nProf    \u2192 ses propres d\u00e9clarations\nParent  \u2192 les cours d\u00e9clar\u00e9s pour lui\nAdmin   \u2192 tous (filtre ?status= optionnel)",
                "operationId": "get_timesheet_list",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            },
            "post": {
                "tags": [
                    "Pointage"
                ],
                "summary": "POST /api/timesheets\nLe professeur d\u00e9clare un cours effectu\u00e9.",
                "description": "Body requis :\n  parentProfileId  : int    \u2014 ID du parent b\u00e9n\u00e9ficiaire\n  startDate        : string \u2014 \"2025-11-15\"\n  durationMinutes  : int    \u2014 dur\u00e9e en minutes (60, 90, 120\u2026)\n  subjectLabel     : string \u2014 libell\u00e9 de la mati\u00e8re (d\u00e9normalis\u00e9)\n\nBody optionnel :\n  subjectId        : int    \u2014 FK vers Subject (pour les stats)\n  startTime        : string \u2014 \"14:30\"\n  levelLabel       : string \u2014 niveau de l'\u00e9l\u00e8ve\n  classLabel       : string \u2014 classe de l'\u00e9l\u00e8ve (ex: \"3\u00e8me B\")\n  studentFirstname : string \u2014 pr\u00e9nom de l'\u00e9l\u00e8ve\n  customAddress    : string \u2014 adresse du cours si diff\u00e9rente",
                "operationId": "post_timesheet_declare",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/parent-info/{profileUuid}": {
            "get": {
                "tags": [
                    "Pointage"
                ],
                "summary": "GET /api/parent-info/{profileUuid}\nPour un professeur : retourne les enfants + mati\u00e8res du contrat actif d'un parent.",
                "operationId": "get_teacher_parent_info",
                "parameters": [
                    {
                        "name": "profileUuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/teacher/families": {
            "get": {
                "tags": [
                    "Pointage"
                ],
                "summary": "GET /api/teacher/families\nFamilles avec lesquelles le prof a travaill\u00e9 ET qui ont au moins un enfant sous contrat actif.",
                "description": "Retourne uniquement le r\u00e9sum\u00e9 (nom + compteurs) \u2014 les d\u00e9tails enfants/mati\u00e8res\nsont charg\u00e9s s\u00e9par\u00e9ment via GET /api/parent-info/{uuid}.",
                "operationId": "get_teacher_families",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/timesheets/{id}/validate": {
            "patch": {
                "tags": [
                    "Pointage"
                ],
                "summary": "PATCH /api/timesheets/{id}/validate\nLe parent confirme que le cours a bien eu lieu.",
                "operationId": "patch_timesheet_validate_parent",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/timesheets/{id}/adjust": {
            "patch": {
                "tags": [
                    "Pointage"
                ],
                "summary": "PATCH /api/timesheets/{id}/adjust\nLe parent corrige la dur\u00e9e avant de valider.",
                "operationId": "patch_timesheet_adjust_parent",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/timesheets/{id}/validate": {
            "patch": {
                "tags": [
                    "Pointage"
                ],
                "summary": "PATCH /api/admin/timesheets/{id}/validate\nValidation finale par l'admin.",
                "description": "Body optionnel :\ndurationMinutes  : int    \u2014 ajuster la dur\u00e9e avant validation\nstartTime        : string \u2014 ajuster l'heure de d\u00e9but (\"HH:MM\")\nlessonRequestUuid: string \u2014 lier ce pointage \u00e0 une commande en attente (cr\u00e9e session assign\u00e9e)",
                "operationId": "patch_admin_timesheet_validate",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/timesheets/{id}": {
            "delete": {
                "tags": [
                    "Pointage"
                ],
                "summary": "DELETE /api/timesheets/{id}\nSupprime un pointage \u2014 uniquement possible si le statut est encore 'teacher_declared'.",
                "description": "Le prof peut supprimer ses propres d\u00e9clarations ; l'admin peut supprimer n'importe lequel.",
                "operationId": "delete_timesheet_delete",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/newsletter/subscribe": {
            "post": {
                "tags": [
                    "Newsletter"
                ],
                "summary": "POST /api/newsletter/subscribe\nInscrire un email \u00e0 la newsletter.",
                "description": "Body : { email }",
                "operationId": "post_newsletter_subscribe",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/newsletter/check": {
            "get": {
                "tags": [
                    "Newsletter"
                ],
                "summary": "GET /api/newsletter/check?email=...\nV\u00e9rifier si une adresse est d\u00e9j\u00e0 inscrite.",
                "operationId": "get_newsletter_check",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/newsletter/admin/subscribers": {
            "get": {
                "tags": [
                    "Newsletter"
                ],
                "summary": "GET /api/admin/newsletter/subscribers\nListe tous les abonn\u00e9s (admin).",
                "operationId": "get_admin_newsletter_list",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/profile/addresses": {
            "get": {
                "tags": [
                    "Adresses"
                ],
                "summary": "GET /api/profile/addresses\nListe toutes les adresses du profil connect\u00e9.",
                "operationId": "get_address_list",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            },
            "post": {
                "tags": [
                    "Adresses"
                ],
                "summary": "POST /api/profile/addresses\nCr\u00e9e une nouvelle adresse pour le profil connect\u00e9.",
                "description": "Body : { label, street, streetComplement?, postalCode, city, country?, latitude?, longitude?, isDefault? }",
                "operationId": "post_address_create",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/profile/addresses/{id}": {
            "delete": {
                "tags": [
                    "Adresses"
                ],
                "summary": "DELETE /api/profile/addresses/{id}\nSupprime une adresse du profil.",
                "operationId": "delete_address_delete",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            },
            "patch": {
                "tags": [
                    "Adresses"
                ],
                "summary": "PATCH /api/profile/addresses/{id}\nModifie une adresse existante (identifiant ProfileAddress).",
                "operationId": "patch_address_update",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/profile/addresses/{id}/default": {
            "patch": {
                "tags": [
                    "Adresses"
                ],
                "summary": "PATCH /api/profile/addresses/{id}/default\nD\u00e9finit cette adresse comme adresse par d\u00e9faut.",
                "operationId": "patch_address_set_default",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/children": {
            "get": {
                "tags": [
                    "Enfants"
                ],
                "summary": "GET /api/children \u2014 liste les enfants du parent connect\u00e9",
                "operationId": "get_children_list",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            },
            "post": {
                "tags": [
                    "Enfants"
                ],
                "summary": "POST /api/children \u2014 cr\u00e9e un enfant et le lie au parent connect\u00e9",
                "operationId": "post_children_create",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/children/{profileUuid}": {
            "patch": {
                "tags": [
                    "Enfants"
                ],
                "summary": "PATCH /api/children/{profileUuid} \u2014 modifie les infos d'un enfant du parent connect\u00e9",
                "operationId": "patch_children_update",
                "parameters": [
                    {
                        "name": "profileUuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/profile": {
            "get": {
                "tags": [
                    "Profil"
                ],
                "summary": "GET /api/profile\nRetourne le profil complet de l'utilisateur connect\u00e9.",
                "operationId": "get_profile_me",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            },
            "patch": {
                "tags": [
                    "Profil"
                ],
                "summary": "PATCH /api/profile\nMise \u00e0 jour des donn\u00e9es personnelles.",
                "description": "Body (tous optionnels) : firstName, lastName, civility, phone, birthDate, about",
                "operationId": "patch_profile_update",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/profile/teacher": {
            "patch": {
                "tags": [
                    "Profil"
                ],
                "summary": "PATCH /api/profile/teacher\nMise \u00e0 jour des donn\u00e9es sp\u00e9cifiques au profil professeur.",
                "description": "Body (tous optionnels) : bio, travelRadiusKm",
                "operationId": "patch_profile_teacher_update",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/profile/picture": {
            "post": {
                "tags": [
                    "Profil"
                ],
                "summary": "POST /api/profile/picture\nUpload de la photo de profil (multipart/form-data, champ \"file\").",
                "operationId": "post_profile_picture_upload",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            },
            "delete": {
                "tags": [
                    "Profil"
                ],
                "summary": "DELETE /api/profile/picture\nSupprime la photo de profil.",
                "operationId": "delete_profile_picture_delete",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/subjects": {
            "get": {
                "tags": [
                    "R\u00e9f\u00e9rentiels"
                ],
                "summary": "GET /api/subjects\nToutes les mati\u00e8res actives (utilis\u00e9e par le front pour les formulaires de commande).",
                "operationId": "get_subject_list",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/teacher/application": {
            "get": {
                "tags": [
                    "Professeurs"
                ],
                "summary": "GET /api/teacher/application\nLe prof voit sa derni\u00e8re candidature.",
                "operationId": "get_teacher_application_my",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            },
            "post": {
                "tags": [
                    "Professeurs"
                ],
                "summary": "POST /api/teacher/application\nLe prof soumet sa candidature.",
                "description": "Cr\u00e9e le TeacherProfile si absent. Refuse si une candidature pending/under_review existe.",
                "operationId": "post_teacher_application_submit",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/teacher/applications/{id}": {
            "get": {
                "tags": [
                    "Professeurs"
                ],
                "summary": "GET /api/admin/teacher/applications/{id}\nRetourne une candidature par son ID (admin uniquement).",
                "operationId": "get_admin_application_show",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/teacher/applications": {
            "get": {
                "tags": [
                    "Professeurs"
                ],
                "summary": "GET /api/admin/teacher/applications\nListe toutes les candidatures. Filtre optionnel : ?status=pending",
                "operationId": "get_admin_application_list",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/teacher/applications/{id}/review": {
            "patch": {
                "tags": [
                    "Professeurs"
                ],
                "summary": "PATCH /api/admin/teacher/applications/{id}/review\nPasse la candidature en \"under_review\" (admin commence l'examen).",
                "operationId": "patch_admin_application_review",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/teacher/applications/{id}/approve": {
            "patch": {
                "tags": [
                    "Professeurs"
                ],
                "summary": "PATCH /api/admin/teacher/applications/{id}/approve\nValide la candidature et active le profil professeur.",
                "operationId": "patch_admin_application_approve",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/teacher/applications/{id}/request-complement": {
            "patch": {
                "tags": [
                    "Professeurs"
                ],
                "summary": "PATCH /api/admin/teacher/applications/{id}/request-complement\nDemande un compl\u00e9ment de dossier au candidat.",
                "description": "Body : { \"comment\": \"Documents manquants ou \u00e0 corriger\u2026\" }\nLe statut reste under_review \u2014 le candidat peut ajouter des documents.",
                "operationId": "patch_admin_application_request_complement",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/admin/teacher/applications/{id}/reject": {
            "patch": {
                "tags": [
                    "Professeurs"
                ],
                "summary": "PATCH /api/admin/teacher/applications/{id}/reject\nRefuse la candidature. Body : { \"comment\": \"...\" }",
                "operationId": "patch_admin_application_reject",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/teacher/application/{id}/documents": {
            "post": {
                "tags": [
                    "Professeurs"
                ],
                "summary": "POST /api/teacher/application/{id}/documents\nUpload d'un document pour une candidature.",
                "description": "Seul le prof propri\u00e9taire (ou un admin) peut uploader.\nFormData : file, type (CV|DIPLOMA|ID_CARD|...)",
                "operationId": "post_teacher_doc_upload",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/teacher/application/{id}/documents/{docId}/download": {
            "get": {
                "tags": [
                    "Professeurs"
                ],
                "summary": "GET /api/teacher/application/{id}/documents/{docId}/download\nT\u00e9l\u00e9charger un document de candidature.",
                "description": "Acc\u00e8s : propri\u00e9taire du dossier ou admin.",
                "operationId": "get_teacher_doc_download",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "docId",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/teacher/application/{id}/documents/{docId}": {
            "delete": {
                "tags": [
                    "Professeurs"
                ],
                "summary": "DELETE /api/teacher/application/{id}/documents/{docId}\nSupprimer un document de candidature.",
                "description": "Acc\u00e8s : propri\u00e9taire (si PENDING ou UNDER_REVIEW) ou admin.",
                "operationId": "delete_teacher_doc_delete",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "docId",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/teachers": {
            "get": {
                "tags": [
                    "Professeurs"
                ],
                "summary": "GET /api/teachers\nListe des professeurs actifs avec leurs mati\u00e8res.",
                "description": "Accessible \u00e0 tous les utilisateurs connect\u00e9s (parents, admins, profs).",
                "operationId": "get_teacher_list",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/teachers/{uuid}": {
            "get": {
                "tags": [
                    "Professeurs"
                ],
                "summary": "GET /api/teachers/{uuid}\nProfil public d'un professeur.",
                "operationId": "get_teacher_detail",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/upload/profile-photo": {
            "post": {
                "tags": [
                    "Upload"
                ],
                "summary": "POST /api/upload/profile-photo\nT\u00e9l\u00e9charge et enregistre la photo de profil de l'utilisateur connect\u00e9.",
                "description": "FormData : file (image JPEG/PNG/WEBP, max 8 Mo)",
                "operationId": "post_upload_profile_photo",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            },
            "delete": {
                "tags": [
                    "Upload"
                ],
                "summary": "DELETE /api/upload/profile-photo\nSupprime la photo de profil de l'utilisateur connect\u00e9.",
                "operationId": "delete_upload_profile_photo_delete",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/upload/signature/{contractUuid}": {
            "post": {
                "tags": [
                    "Upload"
                ],
                "summary": "POST /api/upload/signature/{contractUuid}\nUpload de la signature d'un contrat.",
                "description": "FormData : file (PNG/JPG)\nAcc\u00e8s : propri\u00e9taire du contrat (parent) ou admin.",
                "operationId": "post_upload_signature",
                "parameters": [
                    {
                        "name": "contractUuid",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/upload/temoignage-photo": {
            "post": {
                "tags": [
                    "Upload"
                ],
                "summary": "POST /api/upload/temoignage-photo \u2014 Admin",
                "operationId": "post_upload_temoignage_photo",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/upload/temoignage-photo/{filename}": {
            "delete": {
                "tags": [
                    "Upload"
                ],
                "summary": "DELETE /api/upload/temoignage-photo/{filename} \u2014 Admin",
                "operationId": "delete_upload_temoignage_photo_delete",
                "parameters": [
                    {
                        "name": "filename",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/upload/event-photo": {
            "post": {
                "tags": [
                    "Upload"
                ],
                "summary": "POST /api/upload/event-photo \u2014 Admin",
                "operationId": "post_upload_event_photo",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/upload/event-photo/{filename}": {
            "delete": {
                "tags": [
                    "Upload"
                ],
                "summary": "DELETE /api/upload/event-photo/{filename} \u2014 Admin",
                "operationId": "delete_upload_event_photo_delete",
                "parameters": [
                    {
                        "name": "filename",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/upload/formation-photo": {
            "post": {
                "tags": [
                    "Upload"
                ],
                "summary": "POST /api/upload/formation-photo \u2014 Admin",
                "operationId": "post_upload_formation_photo",
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        },
        "/api/upload/formation-photo/{filename}": {
            "delete": {
                "tags": [
                    "Upload"
                ],
                "summary": "DELETE /api/upload/formation-photo/{filename} \u2014 Admin",
                "operationId": "delete_upload_formation_photo_delete",
                "parameters": [
                    {
                        "name": "filename",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "default": {
                        "description": ""
                    }
                }
            }
        }
    },
    "components": {
        "securitySchemes": {
            "Bearer": {
                "type": "http",
                "description": "Collez votre token JWT ici (sans le pr\u00e9fixe 'Bearer')",
                "bearerFormat": "JWT",
                "scheme": "bearer"
            },
            "JWT": {
                "type": "http",
                "bearerFormat": "JWT",
                "scheme": "bearer"
            }
        }
    },
    "security": [
        {
            "Bearer": []
        }
    ],
    "tags": [
        {
            "name": "Auth",
            "description": "Connexion JWT, inscription en 3 \u00e9tapes (email \u2192 code \u2192 mot de passe)"
        },
        {
            "name": "Authentification",
            "description": "Changement d'email et de mot de passe pour l'utilisateur connect\u00e9"
        },
        {
            "name": "Profil",
            "description": "Consultation et mise \u00e0 jour du profil de l'utilisateur connect\u00e9"
        },
        {
            "name": "Adresses",
            "description": "Adresses enregistr\u00e9es par l'utilisateur connect\u00e9"
        },
        {
            "name": "Enfants",
            "description": "Profils enfants rattach\u00e9s au compte parent connect\u00e9"
        },
        {
            "name": "Professeurs",
            "description": "Liste publique des profs, candidature enseignant, documents"
        },
        {
            "name": "Disponibilit\u00e9s",
            "description": "Cr\u00e9neaux hebdomadaires et indisponibilit\u00e9s des professeurs"
        },
        {
            "name": "Cours",
            "description": "Demandes de cours (parents) et sessions planifi\u00e9es"
        },
        {
            "name": "Sessions",
            "description": "Sessions de cours \u2014 statuts, annulation, reprogrammation"
        },
        {
            "name": "Rapports",
            "description": "Rapports de cours r\u00e9dig\u00e9s par les professeurs apr\u00e8s s\u00e9ance"
        },
        {
            "name": "Livret",
            "description": "Livret de suivi des \u00e9l\u00e8ves (vue professeur et vue parent)"
        },
        {
            "name": "Pointage",
            "description": "Feuilles de pr\u00e9sence d\u00e9clar\u00e9es par les professeurs"
        },
        {
            "name": "Contrats",
            "description": "Contrats parents \u2014 liste, d\u00e9tail, signature, PDF"
        },
        {
            "name": "TeacherContrats",
            "description": "Contrats professeurs \u2014 liste, d\u00e9tail, signature, PDF"
        },
        {
            "name": "Documents",
            "description": "Documents personnels upload\u00e9s (carte identit\u00e9, dipl\u00f4mes\u2026)"
        },
        {
            "name": "Upload",
            "description": "Upload d'images (photo de profil, signature, image contenu)"
        },
        {
            "name": "R\u00e9f\u00e9rentiels",
            "description": "Mati\u00e8res enseign\u00e9es \u2014 lecture publique, CRUD admin"
        },
        {
            "name": "Contact",
            "description": "Formulaires de contact et d'aide en ligne"
        },
        {
            "name": "Leads",
            "description": "Formulaire de prise de contact commercial (visiteur non connect\u00e9)"
        },
        {
            "name": "Newsletter",
            "description": "Abonnement \u00e0 la newsletter et gestion admin des abonn\u00e9s"
        },
        {
            "name": "T\u00e9moignages",
            "description": "T\u00e9moignages clients \u2014 soumission publique et mod\u00e9ration admin"
        },
        {
            "name": "\u00c9v\u00e9nements",
            "description": "\u00c9v\u00e9nements publi\u00e9s sur la vitrine \u2014 liste publique et CRUD admin"
        },
        {
            "name": "Formations",
            "description": "Formations publi\u00e9es sur la vitrine \u2014 liste publique et CRUD admin"
        },
        {
            "name": "Mailing",
            "description": "Campagnes email group\u00e9es et newsletter \u2014 r\u00e9serv\u00e9 ROLE_ADMIN"
        },
        {
            "name": "Admin",
            "description": "Routes d'administration g\u00e9n\u00e9rales \u2014 requiert ROLE_ADMIN"
        },
        {
            "name": "Admin Agenda",
            "description": "Agenda consolid\u00e9 des profs \u2014 vue admin"
        },
        {
            "name": "Admin Stats",
            "description": "Statistiques d'activit\u00e9 et de prestations \u2014 vue admin"
        },
        {
            "name": "Login Check",
            "description": "Login Check"
        }
    ]
}