{"openapi":"3.1.0","info":{"title":"Akwaba AI · API","description":"**Akwaba AI** — Mobility Intelligence multi-pays UEMOA.\n\nPlateforme VTC, livraisons C2C, transport scolaire, B2B entreprises, covoiturage, signalements routiers.\n\n**8 pays UEMOA actifs** : Côte d'Ivoire, Sénégal, Bénin, Burkina Faso, Mali, Niger, Togo, Guinée-Bissau.\n\n**Stack** : FastAPI 0.115 · PostgreSQL 16 + PostGIS · Redis 7 · Anthropic Claude Haiku · Firebase Cloud Messaging · Google Maps.\n\n**Auth** : JWT Bearer (HS256, 30 jours) sur la plupart des endpoints. Endpoints admin via header `X-Admin-Password`.\n\n**Sécurité** : 4 couches de validation signalements crowdsourcés, double code 4 chiffres pour livraisons, pseudo public pour anonymat ethno-régional, archivage automatique des comptes par le temps (125 ans paramétrable via Hub Pixel AI).\n\nPour démarrer : `POST /api/v1/auth/init` → `POST /api/v1/auth/verify` → récupère un JWT, ensuite tous les autres endpoints sont accessibles.","contact":{"name":"Akwaba AI","url":"https://pixelakwaba.com/","email":"support@pixelakwaba.com"},"license":{"name":"Akwaba AI Terms of Service","url":"https://pixelakwaba.com/"},"version":"0.31.0"},"paths":{"/api/v1/auth/init":{"post":{"tags":["auth"],"summary":"Auth Init","description":"Étape 1 : envoie OTP par SMS, retourne un pending_token à utiliser pour la vérification.","operationId":"auth_init_api_v1_auth_init_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthInitIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthInitOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/verify":{"post":{"tags":["auth"],"summary":"Auth Verify","description":"Étape 2 : vérifie OTP, crée user si besoin via Hub, retourne JWT.","operationId":"auth_verify_api_v1_auth_verify_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthVerifyIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthVerifyOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/me":{"get":{"tags":["auth"],"summary":"Auth Me","description":"Retourne l'identité du user via JWT (header Authorization: Bearer ...).","operationId":"auth_me_api_v1_auth_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/auth/identite-civile":{"get":{"tags":["identite-civile"],"summary":"Consulter Identite Civile","description":"Retourne l'identité civile actuelle du user authentifié.","operationId":"consulter_identite_civile_api_v1_auth_identite_civile_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["identite-civile"],"summary":"Saisir Identite Civile","description":"Saisie initiale ou mise à jour de l'identité civile.\n\nLogique :\n  1. Calcule le hash via le helper SQL `calcul_identite_hash`\n  2. Vérifie via `peut_creer_user_avec_identite` :\n     - peut_creer=TRUE  → met à jour le user (le trigger DB calculera le hash)\n     - peut_creer=FALSE → 409 avec raison ('parents_requis' ou 'doublon_avere')","operationId":"saisir_identite_civile_api_v1_auth_identite_civile_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdentiteCivileIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IdentiteCivileOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/radars/":{"get":{"tags":["radars"],"summary":"List Radars Proches","description":"Renvoie les radars fixes dans le rayon donné, triés par distance.","operationId":"list_radars_proches_api_v1_radars__get","parameters":[{"name":"lat","in":"query","required":true,"schema":{"type":"number","maximum":90,"minimum":-90,"description":"Latitude utilisateur","title":"Lat"},"description":"Latitude utilisateur"},{"name":"lon","in":"query","required":true,"schema":{"type":"number","maximum":180,"minimum":-180,"description":"Longitude utilisateur","title":"Lon"},"description":"Longitude utilisateur"},{"name":"rayon_m","in":"query","required":false,"schema":{"type":"integer","maximum":50000,"minimum":100,"description":"Rayon en mètres","default":5000,"title":"Rayon M"},"description":"Rayon en mètres"},{"name":"pays","in":"query","required":false,"schema":{"type":"string","minLength":2,"maxLength":2,"description":"Code pays ISO 2 lettres","default":"CI","title":"Pays"},"description":"Code pays ISO 2 lettres"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RadarOut"},"title":"Response List Radars Proches Api V1 Radars  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/radars/all":{"get":{"tags":["radars"],"summary":"List All Radars","description":"Liste exhaustive des radars d'un pays (à mettre en cache côté client).","operationId":"list_all_radars_api_v1_radars_all_get","parameters":[{"name":"pays","in":"query","required":false,"schema":{"type":"string","minLength":2,"maxLength":2,"default":"CI","title":"Pays"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/radars/stats":{"get":{"tags":["radars"],"summary":"Stats Radars","description":"Statistiques publiques sur les radars indexés.","operationId":"stats_radars_api_v1_radars_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/chauffeurs/profil":{"post":{"tags":["chauffeurs"],"summary":"Upsert Profil","description":"Crée ou met à jour le profil chauffeur. Bascule l'utilisateur en mode chauffeur.","operationId":"upsert_profil_api_v1_chauffeurs_profil_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfilChauffeurIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/chauffeurs/me":{"get":{"tags":["chauffeurs"],"summary":"Get Chauffeur Me","description":"Retourne le profil chauffeur complet.","operationId":"get_chauffeur_me_api_v1_chauffeurs_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/chauffeurs/avatars-autorises":{"get":{"tags":["chauffeurs"],"summary":"Get Avatars","description":"Retourne la liste blanche d'emojis pour l'avatar chauffeur.\n\nVisible uniquement par les passagers — l'identité civile reste\nconfidentielle pour les KYC légaux.","operationId":"get_avatars_api_v1_chauffeurs_avatars_autorises_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/chauffeurs/check-pseudo":{"post":{"tags":["chauffeurs"],"summary":"Check Pseudo","description":"Vérifie si un pseudo est dispo (avant submit), sans le sauvegarder.","operationId":"check_pseudo_api_v1_chauffeurs_check_pseudo_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PseudoIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/chauffeurs/pseudo":{"post":{"tags":["chauffeurs"],"summary":"Update Pseudo","description":"Met à jour le pseudo public + avatar emoji.\n\nRègles :\n- Pseudo unique sur la plateforme (case-insensitive)\n- Validation insultes / marques tiers / discriminatoire / usurpation\n- Modifiable 1×/30 jours pour éviter l'évasion d'identité\n- Avatar emoji doit être dans la whitelist\n- Couleur générée automatiquement par trigger DB\n\nVisible uniquement par les passagers — l'admin et l'identité civile\nrestent intacts pour les besoins KYC légaux.","operationId":"update_pseudo_api_v1_chauffeurs_pseudo_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PseudoIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/chauffeurs/vehicule":{"post":{"tags":["chauffeurs"],"summary":"Add Vehicule","operationId":"add_vehicule_api_v1_chauffeurs_vehicule_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VehiculeIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/chauffeurs/vehicules":{"get":{"tags":["chauffeurs"],"summary":"List Vehicules","operationId":"list_vehicules_api_v1_chauffeurs_vehicules_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/chauffeurs/document":{"post":{"tags":["chauffeurs"],"summary":"Add Document","operationId":"add_document_api_v1_chauffeurs_document_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/chauffeurs/documents":{"get":{"tags":["chauffeurs"],"summary":"List Documents","operationId":"list_documents_api_v1_chauffeurs_documents_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/chauffeurs/online":{"post":{"tags":["chauffeurs"],"summary":"Go Online","description":"Démarre une session active (chauffeur visible et disponible).","operationId":"go_online_api_v1_chauffeurs_online_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PositionIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/chauffeurs/offline":{"post":{"tags":["chauffeurs"],"summary":"Go Offline","operationId":"go_offline_api_v1_chauffeurs_offline_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/chauffeurs/position":{"post":{"tags":["chauffeurs"],"summary":"Update Position","description":"Update position GPS du chauffeur. Si en course et < 300m de l'arrivée, déclenche pré-recherche client.","operationId":"update_position_api_v1_chauffeurs_position_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PositionIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/chauffeurs/disponibles-bientot":{"get":{"tags":["chauffeurs"],"summary":"Chauffeurs Disponibles Bientot","description":"Liste les chauffeurs en course qui seront LIBRES dans `dans_min` minutes proche du point (lat,lon).\nPermet à un passager de réserver \"à l'avance\" un chauffeur qui finit sa course actuelle.","operationId":"chauffeurs_disponibles_bientot_api_v1_chauffeurs_disponibles_bientot_get","parameters":[{"name":"lat","in":"query","required":true,"schema":{"type":"number","title":"Lat"}},{"name":"lon","in":"query","required":true,"schema":{"type":"number","title":"Lon"}},{"name":"dans_min","in":"query","required":false,"schema":{"type":"integer","default":15,"title":"Dans Min"}},{"name":"rayon_m","in":"query","required":false,"schema":{"type":"integer","default":5000,"title":"Rayon M"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/chauffeurs/proches":{"get":{"tags":["chauffeurs"],"summary":"Chauffeurs Proches","description":"Retourne les chauffeurs actuellement online dans un rayon donné.","operationId":"chauffeurs_proches_api_v1_chauffeurs_proches_get","parameters":[{"name":"lat","in":"query","required":true,"schema":{"type":"number","title":"Lat"}},{"name":"lon","in":"query","required":true,"schema":{"type":"number","title":"Lon"}},{"name":"rayon_m","in":"query","required":false,"schema":{"type":"integer","default":5000,"title":"Rayon M"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/chauffeurs/stats":{"get":{"tags":["chauffeurs"],"summary":"Stats Chauffeur","operationId":"stats_chauffeur_api_v1_chauffeurs_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/courses/devis":{"get":{"tags":["courses"],"summary":"Devis","description":"Devis suggéré pour une course donnée.\nCombine le barème de la ville (`tarifs_marche_ville`) et le multiplier surge\nactif du chauffeur (`chauffeur_tarif_multiplier`).\nLe chauffeur reste libre de facturer ce qu'il veut au final.","operationId":"devis_api_v1_courses_devis_get","parameters":[{"name":"distance_km","in":"query","required":true,"schema":{"type":"number","title":"Distance Km"}},{"name":"duree_min","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Duree Min"}},{"name":"ville_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Ville Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevisOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/courses/":{"post":{"tags":["courses"],"summary":"Start Course","description":"Le chauffeur démarre une course. Si arrivée + distance fournies, calcule ETA et met à jour session\npour que le chauffeur compte comme 'libre dans X min à destination'.","operationId":"start_course_api_v1_courses__post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CourseStartWithDestIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/courses/{course_id}/terminer":{"post":{"tags":["courses"],"summary":"End Course","operationId":"end_course_api_v1_courses__course_id__terminer_post","parameters":[{"name":"course_id","in":"path","required":true,"schema":{"type":"string","title":"Course Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CourseEndIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/courses/{course_id}/annuler":{"post":{"tags":["courses"],"summary":"Cancel Course","description":"Annulation d'une course par le passager OU le chauffeur.\n\nFrais d'annulation calculés selon délai depuis acceptation :\n- Passager : 0 < 1min, 500 < 5min, 1000 < 10min, 1500 > 10min\n- Chauffeur : 0 < 1min, 1000 < 5min, 2000 > 5min\n\nLe chauffeur récupère 80% des frais (compensation),\nAkwaba garde 20% (frais de service).","operationId":"cancel_course_api_v1_courses__course_id__annuler_post","parameters":[{"name":"course_id","in":"path","required":true,"schema":{"type":"string","title":"Course Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnnulerIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/courses/{course_id}/demarrer-avec-code":{"post":{"tags":["courses"],"summary":"Demarrer Avec Code","description":"Le chauffeur saisit le code 4 chiffres donné par le passager pour\ndémarrer effectivement la course (anti-faux-chauffeur).\n\nAprès 3 tentatives ratées → alerte sécurité automatique.","operationId":"demarrer_avec_code_api_v1_courses__course_id__demarrer_avec_code_post","parameters":[{"name":"course_id","in":"path","required":true,"schema":{"type":"string","title":"Course Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeDemarrageIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/courses/{course_id}/mon-code":{"get":{"tags":["courses"],"summary":"Mon Code Demarrage","description":"Le passager récupère son code 4 chiffres à donner au chauffeur.\nVisible UNIQUEMENT par le passager de la course.","operationId":"mon_code_demarrage_api_v1_courses__course_id__mon_code_get","parameters":[{"name":"course_id","in":"path","required":true,"schema":{"type":"string","title":"Course Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/courses/historique":{"get":{"tags":["courses"],"summary":"Historique","description":"Historique des courses (en tant que chauffeur OU passager selon le rôle).","operationId":"historique_api_v1_courses_historique_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":30,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/courses/{course_id}":{"get":{"tags":["courses"],"summary":"Get Course","operationId":"get_course_api_v1_courses__course_id__get","parameters":[{"name":"course_id","in":"path","required":true,"schema":{"type":"string","title":"Course Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/courses/{course_id}/noter":{"post":{"tags":["courses"],"summary":"Noter Course","description":"Le chauffeur note le passager OU le passager note le chauffeur.\n\nRègles :\n- La course doit être terminée\n- On ne peut noter qu'UNE seule fois (pas de re-notation)\n- Note 1-5, commentaire optionnel\n- Les triggers SQL recalculent automatiquement note_moyenne + suspensions\n\nNB: pas de fenêtre de temps limite pour noter (on accepte les notes\nrétroactives, la pression sociale fait déjà le travail).","operationId":"noter_course_api_v1_courses__course_id__noter_post","parameters":[{"name":"course_id","in":"path","required":true,"schema":{"type":"string","title":"Course Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NoteIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/courses/{course_id}/aller-retour/attente-debut":{"post":{"tags":["courses"],"summary":"Ar Attente Debut","description":"Chauffeur signale qu'il est arrive au point d'attente A/R.\nDemarre le compteur d'attente facturee.","operationId":"ar_attente_debut_api_v1_courses__course_id__aller_retour_attente_debut_post","parameters":[{"name":"course_id","in":"path","required":true,"schema":{"type":"string","title":"Course Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/courses/{course_id}/aller-retour/attente-fin":{"post":{"tags":["courses"],"summary":"Ar Attente Fin","description":"Chauffeur signale qu'il redemarre. Calcule duree reelle + montant attente\n+ bascule retour_en_cours=TRUE.","operationId":"ar_attente_fin_api_v1_courses__course_id__aller_retour_attente_fin_post","parameters":[{"name":"course_id","in":"path","required":true,"schema":{"type":"string","title":"Course Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/courses/{course_id}/aller-retour":{"get":{"tags":["courses"],"summary":"Ar Status","description":"Status de l'aller-retour : phases (aller / attente / retour) + montants.","operationId":"ar_status_api_v1_courses__course_id__aller_retour_get","parameters":[{"name":"course_id","in":"path","required":true,"schema":{"type":"string","title":"Course Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/courses/{course_id}/arrets":{"post":{"tags":["arrets"],"summary":"Ajouter Arret","description":"Le passager ajoute un arrêt à la course en cours.\n\nConditions :\n- course doit exister, statut 'en_cours' ou 'acceptee'\n- user doit être le passager de la course\n- max 3 arrêts à chaud actifs par course (anti-abus)","operationId":"ajouter_arret_api_v1_courses__course_id__arrets_post","parameters":[{"name":"course_id","in":"path","required":true,"schema":{"type":"string","title":"Course Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArretIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["arrets"],"summary":"Lister Arrets","description":"Liste les arrêts d'une course (passager OU chauffeur).","operationId":"lister_arrets_api_v1_courses__course_id__arrets_get","parameters":[{"name":"course_id","in":"path","required":true,"schema":{"type":"string","title":"Course Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/courses/{course_id}/arrets/{arret_id}":{"delete":{"tags":["arrets"],"summary":"Annuler Arret","description":"Le passager annule un arrêt (uniquement si statut=propose, pas encore accepté).","operationId":"annuler_arret_api_v1_courses__course_id__arrets__arret_id__delete","parameters":[{"name":"course_id","in":"path","required":true,"schema":{"type":"string","title":"Course Id"}},{"name":"arret_id","in":"path","required":true,"schema":{"type":"integer","title":"Arret Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/courses/{course_id}/arrets/{arret_id}/accepter":{"post":{"tags":["arrets"],"summary":"Accepter Arret","description":"Chauffeur accepte la demande d'arrêt.","operationId":"accepter_arret_api_v1_courses__course_id__arrets__arret_id__accepter_post","parameters":[{"name":"course_id","in":"path","required":true,"schema":{"type":"string","title":"Course Id"}},{"name":"arret_id","in":"path","required":true,"schema":{"type":"integer","title":"Arret Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/courses/{course_id}/arrets/{arret_id}/refuser":{"post":{"tags":["arrets"],"summary":"Refuser Arret","description":"Chauffeur refuse la demande d'arrêt avec une raison optionnelle.","operationId":"refuser_arret_api_v1_courses__course_id__arrets__arret_id__refuser_post","parameters":[{"name":"course_id","in":"path","required":true,"schema":{"type":"string","title":"Course Id"}},{"name":"arret_id","in":"path","required":true,"schema":{"type":"integer","title":"Arret Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefusIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/courses/{course_id}/arrets/{arret_id}/arrive":{"post":{"tags":["arrets"],"summary":"Chauffeur Arrive","description":"Le chauffeur signale qu'il est arrivé sur place. Démarre le compteur d'attente.","operationId":"chauffeur_arrive_api_v1_courses__course_id__arrets__arret_id__arrive_post","parameters":[{"name":"course_id","in":"path","required":true,"schema":{"type":"string","title":"Course Id"}},{"name":"arret_id","in":"path","required":true,"schema":{"type":"integer","title":"Arret Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/courses/{course_id}/arrets/{arret_id}/reparti":{"post":{"tags":["arrets"],"summary":"Chauffeur Reparti","description":"Le chauffeur redémarre. Calcule durée et montant facturé.","operationId":"chauffeur_reparti_api_v1_courses__course_id__arrets__arret_id__reparti_post","parameters":[{"name":"course_id","in":"path","required":true,"schema":{"type":"string","title":"Course Id"}},{"name":"arret_id","in":"path","required":true,"schema":{"type":"integer","title":"Arret Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/courses/{course_id}/reroute":{"post":{"tags":["reroute"],"summary":"Proposer Reroute","description":"Passager propose une nouvelle destination en pleine course.\n\nContraintes :\n- course doit etre 'en_cours' ou 'acceptee'\n- user doit etre le passager\n- 1 seul reroute actif (propose) a la fois par course (anti-abus)","operationId":"proposer_reroute_api_v1_courses__course_id__reroute_post","parameters":[{"name":"course_id","in":"path","required":true,"schema":{"type":"string","title":"Course Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RerouteIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/courses/{course_id}/reroutes":{"get":{"tags":["reroute"],"summary":"Lister Reroutes","operationId":"lister_reroutes_api_v1_courses__course_id__reroutes_get","parameters":[{"name":"course_id","in":"path","required":true,"schema":{"type":"string","title":"Course Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/courses/{course_id}/reroutes/{rid}":{"delete":{"tags":["reroute"],"summary":"Annuler Reroute","description":"Passager annule sa demande de reroute (uniquement si statut='propose').","operationId":"annuler_reroute_api_v1_courses__course_id__reroutes__rid__delete","parameters":[{"name":"course_id","in":"path","required":true,"schema":{"type":"string","title":"Course Id"}},{"name":"rid","in":"path","required":true,"schema":{"type":"integer","title":"Rid"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/courses/{course_id}/reroutes/{rid}/accepter":{"post":{"tags":["reroute"],"summary":"Accepter Reroute","description":"Chauffeur accepte le changement de destination.\n\nEffet :\n- Reroute marque 'accepte'\n- courses.arrivee_geom + arrivee_adresse mis a jour vers la nouvelle destination\n- courses.distance_km augmente du supplement\n- courses.montant_xof augmente du montant supplementaire\n- Ancienne destination archivee dans le reroute (audit)","operationId":"accepter_reroute_api_v1_courses__course_id__reroutes__rid__accepter_post","parameters":[{"name":"course_id","in":"path","required":true,"schema":{"type":"string","title":"Course Id"}},{"name":"rid","in":"path","required":true,"schema":{"type":"integer","title":"Rid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/courses/{course_id}/reroutes/{rid}/refuser":{"post":{"tags":["reroute"],"summary":"Refuser Reroute","description":"Chauffeur refuse le changement. La course continue vers l'ancienne destination.","operationId":"refuser_reroute_api_v1_courses__course_id__reroutes__rid__refuser_post","parameters":[{"name":"course_id","in":"path","required":true,"schema":{"type":"string","title":"Course Id"}},{"name":"rid","in":"path","required":true,"schema":{"type":"integer","title":"Rid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefusIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/notifications/":{"get":{"tags":["notifications"],"summary":"List Notifs","operationId":"list_notifs_api_v1_notifications__get","parameters":[{"name":"lu","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Lu"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/notifications/non-lues":{"get":{"tags":["notifications"],"summary":"Count Non Lues","operationId":"count_non_lues_api_v1_notifications_non_lues_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/notifications/{notif_id}/lue":{"post":{"tags":["notifications"],"summary":"Marquer Lue","operationId":"marquer_lue_api_v1_notifications__notif_id__lue_post","parameters":[{"name":"notif_id","in":"path","required":true,"schema":{"type":"integer","title":"Notif Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/notifications/tout-lues":{"post":{"tags":["notifications"],"summary":"Marquer Tout Lue","operationId":"marquer_tout_lue_api_v1_notifications_tout_lues_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/messages/":{"post":{"tags":["messages"],"summary":"Envoyer Message","operationId":"envoyer_message_api_v1_messages__post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/messages/conversations":{"get":{"tags":["messages"],"summary":"List Conversations","operationId":"list_conversations_api_v1_messages_conversations_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/messages/avec/{autre_id}":{"get":{"tags":["messages"],"summary":"Conversation","operationId":"conversation_api_v1_messages_avec__autre_id__get","parameters":[{"name":"autre_id","in":"path","required":true,"schema":{"type":"integer","title":"Autre Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/forum/posts":{"post":{"tags":["forum"],"summary":"Create Post","operationId":"create_post_api_v1_forum_posts_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["forum"],"summary":"List Posts","operationId":"list_posts_api_v1_forum_posts_get","parameters":[{"name":"categorie","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Categorie"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":30,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/forum/posts/{post_id}":{"get":{"tags":["forum"],"summary":"Get Post","operationId":"get_post_api_v1_forum_posts__post_id__get","parameters":[{"name":"post_id","in":"path","required":true,"schema":{"type":"integer","title":"Post Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/forum/posts/{post_id}/commenter":{"post":{"tags":["forum"],"summary":"Commenter Post","operationId":"commenter_post_api_v1_forum_posts__post_id__commenter_post","parameters":[{"name":"post_id","in":"path","required":true,"schema":{"type":"integer","title":"Post Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommentIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/forum/posts/{post_id}/like":{"post":{"tags":["forum"],"summary":"Like Post","operationId":"like_post_api_v1_forum_posts__post_id__like_post","parameters":[{"name":"post_id","in":"path","required":true,"schema":{"type":"integer","title":"Post Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/paiements/checkout":{"post":{"tags":["paiements"],"summary":"Checkout","description":"Crée une intention de paiement PayTech, retourne l'URL de redirection mobile money.","operationId":"checkout_api_v1_paiements_checkout_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/paiements/webhook/paytech":{"post":{"tags":["paiements"],"summary":"Paytech Ipn","description":"IPN PayTech — appelé par PayTech après paiement (succès ou échec).","operationId":"paytech_ipn_api_v1_paiements_webhook_paytech_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/paiements/{paiement_id}":{"get":{"tags":["paiements"],"summary":"Get Paiement","operationId":"get_paiement_api_v1_paiements__paiement_id__get","parameters":[{"name":"paiement_id","in":"path","required":true,"schema":{"type":"string","title":"Paiement Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/paiements/":{"get":{"tags":["paiements"],"summary":"List Paiements","operationId":"list_paiements_api_v1_paiements__get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":30,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/demandes/":{"post":{"tags":["demandes"],"summary":"Creer Demande","description":"Créer une demande de course :\n1. Vérifie d'abord les chauffeurs préférentiels online (peu importe distance)\n2. Lance EN PARALLÈLE le ring-search normal (300m → 1.5km → 5km → 10km)\n3. Retourne les 2 listes — l'app décide d'attendre les pref ou de prendre les ring\n\nSi au moins 1 chauffeur préférentiel est en session active, il est listé\nen premier (ordre 1, 2, 3) avec sa distance actuelle. Le passager peut\nchoisir d'attendre ou d'utiliser un chauffeur du ring search.","operationId":"creer_demande_api_v1_demandes__post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DemandeCourseIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/demandes/{demande_id}/proposer-a/{chauffeur_id}":{"post":{"tags":["demandes"],"summary":"Proposer Demande A","description":"Le passager choisit un chauffeur (parmi plus_proche, preferentiel ou autre).\nLa demande est réservée pour ce chauffeur pendant 60 secondes.\nPendant ce temps, aucun autre chauffeur ne peut accepter.\nSi le chauffeur refuse ou ne répond pas, la demande redevient ouverte.","operationId":"proposer_demande_a_api_v1_demandes__demande_id__proposer_a__chauffeur_id__post","parameters":[{"name":"demande_id","in":"path","required":true,"schema":{"type":"integer","title":"Demande Id"}},{"name":"chauffeur_id","in":"path","required":true,"schema":{"type":"integer","title":"Chauffeur Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/demandes/{demande_id}/refuser":{"post":{"tags":["demandes"],"summary":"Chauffeur Refuse Demande","description":"Le chauffeur refuse une demande qui lui est réservée.\nLa réservation est libérée immédiatement, la demande redevient ouverte.","operationId":"chauffeur_refuse_demande_api_v1_demandes__demande_id__refuser_post","parameters":[{"name":"demande_id","in":"path","required":true,"schema":{"type":"integer","title":"Demande Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/demandes/{demande_id}/dispatcher":{"post":{"tags":["demandes"],"summary":"Relancer Dispatcher","description":"Relance le ring-search pour une demande encore ouverte.\nUtile si les premiers chauffeurs notifiés n'ont pas accepté en 30-60 sec.\nLa fonction SQL exclut automatiquement les chauffeurs déjà notifiés et\nélargit le rayon si nécessaire.","operationId":"relancer_dispatcher_api_v1_demandes__demande_id__dispatcher_post","parameters":[{"name":"demande_id","in":"path","required":true,"schema":{"type":"integer","title":"Demande Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/demandes/{demande_id}/dispatch-status":{"get":{"tags":["demandes"],"summary":"Dispatch Status","description":"État du dispatching d'une demande (étape, rayon, chauffeurs notifiés).","operationId":"dispatch_status_api_v1_demandes__demande_id__dispatch_status_get","parameters":[{"name":"demande_id","in":"path","required":true,"schema":{"type":"integer","title":"Demande Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/demandes/proches":{"get":{"tags":["demandes"],"summary":"Demandes Proches","description":"Liste les demandes de course ouvertes dans un rayon — vue chauffeur.\n\nEXCLUT automatiquement :\n- Les demandes des passagers blacklistés mutuellement\n- Les demandes réservées à un autre chauffeur\n- Si mode \"Rentrer chez moi\" actif : les courses qui ne rapprochent pas\n  le chauffeur de sa destination","operationId":"demandes_proches_api_v1_demandes_proches_get","parameters":[{"name":"lat","in":"query","required":true,"schema":{"type":"number","title":"Lat"}},{"name":"lon","in":"query","required":true,"schema":{"type":"number","title":"Lon"}},{"name":"rayon_m","in":"query","required":false,"schema":{"type":"integer","default":5000,"title":"Rayon M"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/demandes/{demande_id}/accepter":{"post":{"tags":["demandes"],"summary":"Accepter Demande","description":"Le chauffeur accepte une demande.\nRègles :\n- Si la demande a été RÉSERVÉE pour un chauffeur précis (chauffeur_propose_id),\n  seul ce chauffeur peut l'accepter pendant la fenêtre de 60 sec.\n- Hors fenêtre ou pas de réservation : tout chauffeur peut accepter.","operationId":"accepter_demande_api_v1_demandes__demande_id__accepter_post","parameters":[{"name":"demande_id","in":"path","required":true,"schema":{"type":"integer","title":"Demande Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/demandes/{demande_id}/annuler":{"post":{"tags":["demandes"],"summary":"Annuler Demande","operationId":"annuler_demande_api_v1_demandes__demande_id__annuler_post","parameters":[{"name":"demande_id","in":"path","required":true,"schema":{"type":"integer","title":"Demande Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/demandes/mes":{"get":{"tags":["demandes"],"summary":"Mes Demandes","operationId":"mes_demandes_api_v1_demandes_mes_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":30,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/demandes/courses/{course_id}/colis/codes":{"get":{"tags":["demandes"],"summary":"Expediteur Recupere Codes","description":"L'expéditeur récupère SES codes (retrait à donner au chauffeur,\ndépôt à transmettre au destinataire). Accès limité au passager\nqui a créé la demande de livraison.","operationId":"expediteur_recupere_codes_api_v1_demandes_courses__course_id__colis_codes_get","parameters":[{"name":"course_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Course Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/demandes/courses/{course_id}/colis/retrait":{"post":{"tags":["demandes"],"summary":"Chauffeur Valide Retrait","description":"Le chauffeur saisit le code RETRAIT fourni par l'expéditeur.\nSi valide, le colis est marqué comme retiré.\nPlafond : 3 tentatives, après quoi le code est bloqué (support).","operationId":"chauffeur_valide_retrait_api_v1_demandes_courses__course_id__colis_retrait_post","parameters":[{"name":"course_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Course Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeColisIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/demandes/courses/{course_id}/colis/depose":{"post":{"tags":["demandes"],"summary":"Chauffeur Valide Depot","description":"Le chauffeur saisit le code DÉPÔT fourni par le destinataire.\nSi valide, le colis est marqué comme livré et la course passe à 'terminee'.","operationId":"chauffeur_valide_depot_api_v1_demandes_courses__course_id__colis_depose_post","parameters":[{"name":"course_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Course Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeColisIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/sos/contacts":{"get":{"tags":["sos"],"summary":"List Sos Contacts","operationId":"list_sos_contacts_api_v1_sos_contacts_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["sos"],"summary":"Add Sos Contact","operationId":"add_sos_contact_api_v1_sos_contacts_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SosContactIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/sos/contacts/{contact_id}":{"delete":{"tags":["sos"],"summary":"Del Sos Contact","operationId":"del_sos_contact_api_v1_sos_contacts__contact_id__delete","parameters":[{"name":"contact_id","in":"path","required":true,"schema":{"type":"integer","title":"Contact Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/sos/declencher":{"post":{"tags":["sos"],"summary":"Declencher Sos","operationId":"declencher_sos_api_v1_sos_declencher_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SosDeclencherIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/cagnotte/":{"get":{"tags":["cagnotte"],"summary":"Get Cagnotte","operationId":"get_cagnotte_api_v1_cagnotte__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/cagnotte/retirer":{"post":{"tags":["cagnotte"],"summary":"Retirer Cagnotte","operationId":"retirer_cagnotte_api_v1_cagnotte_retirer_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetraitIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/cagnotte/retraits":{"get":{"tags":["cagnotte"],"summary":"List Retraits","operationId":"list_retraits_api_v1_cagnotte_retraits_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/tarifs/perso":{"get":{"tags":["tarifs"],"summary":"Get Tarifs","operationId":"get_tarifs_api_v1_tarifs_perso_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["tarifs"],"summary":"Update Tarifs","description":"Le chauffeur fixe son propre tarif (avantage clé vs Yango qui impose).","operationId":"update_tarifs_api_v1_tarifs_perso_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TarifIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/tarifs/estimer":{"get":{"tags":["tarifs"],"summary":"Estimer Course","description":"Calcule le prix qu'aurait cette course selon les tarifs du chauffeur.","operationId":"estimer_course_api_v1_tarifs_estimer_get","parameters":[{"name":"distance_km","in":"query","required":true,"schema":{"type":"number","title":"Distance Km"}},{"name":"duree_min","in":"query","required":true,"schema":{"type":"integer","title":"Duree Min"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/tarifs/marche":{"get":{"tags":["tarifs"],"summary":"Tarif Marche","description":"Tarifs indicatifs marché Abidjan (référence pour les chauffeurs).","operationId":"tarif_marche_api_v1_tarifs_marche_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/gamification/badges":{"get":{"tags":["gamification"],"summary":"List Badges","description":"Liste des badges disponibles (catalogue public).","operationId":"list_badges_api_v1_gamification_badges_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/gamification/mes-badges":{"get":{"tags":["gamification"],"summary":"Mes Badges","operationId":"mes_badges_api_v1_gamification_mes_badges_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/gamification/classement":{"get":{"tags":["gamification"],"summary":"Classement Chauffeurs","description":"Top chauffeurs par revenus du mois courant.","operationId":"classement_chauffeurs_api_v1_gamification_classement_get","parameters":[{"name":"periode","in":"query","required":false,"schema":{"type":"string","default":"mois","title":"Periode"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/gamification/parrainer":{"post":{"tags":["gamification"],"summary":"Utiliser Code Parrain","description":"Le user (filleul) utilise le code09 d'un parrain pour bénéficier d'un bonus.","operationId":"utiliser_code_parrain_api_v1_gamification_parrainer_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParrainageIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/gamification/mes-filleuls":{"get":{"tags":["gamification"],"summary":"Mes Filleuls","operationId":"mes_filleuls_api_v1_gamification_mes_filleuls_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/gamification/formations":{"get":{"tags":["gamification"],"summary":"List Formations","operationId":"list_formations_api_v1_gamification_formations_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/gamification/formations/completer":{"post":{"tags":["gamification"],"summary":"Completer Formation","operationId":"completer_formation_api_v1_gamification_formations_completer_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FormationCompleteIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/zones/":{"get":{"tags":["zones"],"summary":"List Zones Rentables","description":"Liste des zones rentables proches (heatmap chauffeur).","operationId":"list_zones_rentables_api_v1_zones__get","parameters":[{"name":"lat","in":"query","required":true,"schema":{"type":"number","title":"Lat"}},{"name":"lon","in":"query","required":true,"schema":{"type":"number","title":"Lon"}},{"name":"rayon_m","in":"query","required":false,"schema":{"type":"integer","default":10000,"title":"Rayon M"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/zones/stats-courses":{"get":{"tags":["zones"],"summary":"Stats Courses Par Zone","description":"Stats agrégées des courses du chauffeur par commune (depuis le départ).","operationId":"stats_courses_par_zone_api_v1_zones_stats_courses_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/villes/":{"get":{"tags":["villes"],"summary":"List Villes","description":"Liste publique des villes couvertes.","operationId":"list_villes_api_v1_villes__get","parameters":[{"name":"pays","in":"query","required":false,"schema":{"type":"string","default":"CI","title":"Pays"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Q"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/villes/proche":{"get":{"tags":["villes"],"summary":"Ville Proche","description":"Retourne la ville la plus proche d'un point GPS.","operationId":"ville_proche_api_v1_villes_proche_get","parameters":[{"name":"lat","in":"query","required":true,"schema":{"type":"number","title":"Lat"}},{"name":"lon","in":"query","required":true,"schema":{"type":"number","title":"Lon"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/villes/{ville_id}":{"get":{"tags":["villes"],"summary":"Get Ville","description":"Détail ville + tarifs marché + stats.","operationId":"get_ville_api_v1_villes__ville_id__get","parameters":[{"name":"ville_id","in":"path","required":true,"schema":{"type":"integer","title":"Ville Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/villes/{ville_id}/stats":{"get":{"tags":["villes"],"summary":"Ville Stats","description":"Stats activité d'une ville.","operationId":"ville_stats_api_v1_villes__ville_id__stats_get","parameters":[{"name":"ville_id","in":"path","required":true,"schema":{"type":"integer","title":"Ville Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/villes/zones-chauffeur":{"post":{"tags":["villes"],"summary":"Add Zone","description":"Le chauffeur déclare une ville où il opère.","operationId":"add_zone_api_v1_villes_zones_chauffeur_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ZoneIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/villes/zones-chauffeur/me":{"get":{"tags":["villes"],"summary":"My Zones","operationId":"my_zones_api_v1_villes_zones_chauffeur_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/villes/zones-chauffeur/{ville_id}":{"delete":{"tags":["villes"],"summary":"Remove Zone","operationId":"remove_zone_api_v1_villes_zones_chauffeur__ville_id__delete","parameters":[{"name":"ville_id","in":"path","required":true,"schema":{"type":"integer","title":"Ville Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/alertes/proche":{"get":{"tags":["alertes"],"summary":"Alertes Proches","description":"Alertes actives à moins de `rayon_km` de la position GPS donnée.","operationId":"alertes_proches_api_v1_alertes_proche_get","parameters":[{"name":"lat","in":"query","required":true,"schema":{"type":"number","maximum":90,"minimum":-90,"title":"Lat"}},{"name":"lon","in":"query","required":true,"schema":{"type":"number","maximum":180,"minimum":-180,"title":"Lon"}},{"name":"rayon_km","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Rayon Km"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AlerteOut"},"title":"Response Alertes Proches Api V1 Alertes Proche Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/alertes/ville/{ville}":{"get":{"tags":["alertes"],"summary":"Alertes Par Ville","description":"Toutes les alertes actives d'une ville (ex: 'Abidjan', 'Bouake').","operationId":"alertes_par_ville_api_v1_alertes_ville__ville__get","parameters":[{"name":"ville","in":"path","required":true,"schema":{"type":"string","title":"Ville"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AlerteOut"},"title":"Response Alertes Par Ville Api V1 Alertes Ville  Ville  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/alertes/{alerte_id}/voir":{"post":{"tags":["alertes"],"summary":"Alerte Vue","description":"Marque qu'un chauffeur a vu l'alerte (analytics, pas obligatoire mais utile).","operationId":"alerte_vue_api_v1_alertes__alerte_id__voir_post","parameters":[{"name":"alerte_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Alerte Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/alertes/{alerte_id}/accepter":{"post":{"tags":["alertes"],"summary":"Accepter Alerte","description":"Le chauffeur accepte l'alerte et applique un multiplier sur son tarif.\nLe multiplier reste actif jusqu'à expiration de l'alerte (ou max +1h).","operationId":"accepter_alerte_api_v1_alertes__alerte_id__accepter_post","parameters":[{"name":"alerte_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Alerte Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccepterAlerteIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MultiplierOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/alertes/multiplier":{"delete":{"tags":["alertes"],"summary":"Retirer Multiplier","description":"Le chauffeur retire son multiplier (revient à tarif normal).","operationId":"retirer_multiplier_api_v1_alertes_multiplier_delete","responses":{"204":{"description":"Successful Response"}}}},"/api/v1/alertes/mon-multiplier":{"get":{"tags":["alertes"],"summary":"Mon Multiplier","description":"Récupère le multiplier actif du chauffeur (None si aucun).","operationId":"mon_multiplier_api_v1_alertes_mon_multiplier_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/MultiplierOut"},{"type":"null"}],"title":"Response Mon Multiplier Api V1 Alertes Mon Multiplier Get"}}}}}}},"/api/v1/pays":{"get":{"tags":["pays"],"summary":"List Pays Actifs","description":"Liste des pays actifs où Akwaba opère.\nFiltre optionnel par bloc économique : UEMOA, CEMAC, CEDEAO, UMA, EU, NORDAM.","operationId":"list_pays_actifs_api_v1_pays_get","parameters":[{"name":"bloc","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bloc"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/pays/{code}":{"get":{"tags":["pays"],"summary":"Get Pays","description":"Détails d'un pays par code ISO 3166-1 alpha-2 (ex: 'ci', 'sn').","operationId":"get_pays_api_v1_pays__code__get","parameters":[{"name":"code","in":"path","required":true,"schema":{"type":"string","title":"Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/pays/{code}/villes":{"get":{"tags":["pays"],"summary":"List Villes Pays","description":"Villes d'un pays donné, classées par population décroissante.","operationId":"list_villes_pays_api_v1_pays__code__villes_get","parameters":[{"name":"code","in":"path","required":true,"schema":{"type":"string","title":"Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/pays/{code}/mobile-money":{"get":{"tags":["pays"],"summary":"List Mobile Money Pays","description":"Liste des opérateurs mobile money actifs dans un pays.","operationId":"list_mobile_money_pays_api_v1_pays__code__mobile_money_get","parameters":[{"name":"code","in":"path","required":true,"schema":{"type":"string","title":"Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/pays/devises/all":{"get":{"tags":["pays"],"summary":"List Devises","description":"Liste toutes les devises supportées (pour la conversion / affichage UI).","operationId":"list_devises_api_v1_pays_devises_all_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/notations/chauffeur/{chauffeur_id}":{"get":{"tags":["notations"],"summary":"Profil Chauffeur","description":"Profil public d'un chauffeur : note moyenne, distribution, expérience.","operationId":"profil_chauffeur_api_v1_notations_chauffeur__chauffeur_id__get","parameters":[{"name":"chauffeur_id","in":"path","required":true,"schema":{"type":"integer","title":"Chauffeur Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/notations/chauffeur/{chauffeur_id}/commentaires":{"get":{"tags":["notations"],"summary":"Commentaires Chauffeur","description":"Derniers commentaires reçus par un chauffeur (anonymisés, du plus récent).","operationId":"commentaires_chauffeur_api_v1_notations_chauffeur__chauffeur_id__commentaires_get","parameters":[{"name":"chauffeur_id","in":"path","required":true,"schema":{"type":"integer","title":"Chauffeur Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/notations/passager/{passager_id}":{"get":{"tags":["notations"],"summary":"Profil Passager","description":"Profil public d'un passager (visible aux chauffeurs avant d'accepter).","operationId":"profil_passager_api_v1_notations_passager__passager_id__get","parameters":[{"name":"passager_id","in":"path","required":true,"schema":{"type":"integer","title":"Passager Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/notations/passager/{passager_id}/commentaires":{"get":{"tags":["notations"],"summary":"Commentaires Passager","description":"Commentaires reçus par un passager (réservé aux chauffeurs).","operationId":"commentaires_passager_api_v1_notations_passager__passager_id__commentaires_get","parameters":[{"name":"passager_id","in":"path","required":true,"schema":{"type":"integer","title":"Passager Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/notations/me/recues":{"get":{"tags":["notations"],"summary":"Mes Notes Recues","description":"Notes que j'ai reçues, listées par course.\nSi je suis chauffeur, retourne note_chauffeur (donnée par les passagers).\nSi je suis passager, retourne note_passager (donnée par les chauffeurs).","operationId":"mes_notes_recues_api_v1_notations_me_recues_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/notations/me/donnees":{"get":{"tags":["notations"],"summary":"Mes Notes Donnees","description":"Notes que J'AI DONNÉES aux autres.\nSi je suis chauffeur, je donne des notes aux passagers.\nSi je suis passager, je donne des notes aux chauffeurs.","operationId":"mes_notes_donnees_api_v1_notations_me_donnees_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/notations/me/stats":{"get":{"tags":["notations"],"summary":"Mes Stats","description":"Mes stats agrégées (note moyenne, distribution, dernier 30j vs total).","operationId":"mes_stats_api_v1_notations_me_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/blacklists":{"post":{"tags":["blacklists"],"summary":"Creer Blacklist","description":"Blackliste un autre utilisateur. Définitif tant qu'on ne le retire pas.\nLe dispatcher ne nous appariera plus jamais avec lui.","operationId":"creer_blacklist_api_v1_blacklists_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlacklistIn"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/blacklists/{target_user_id}":{"delete":{"tags":["blacklists"],"summary":"Retirer Blacklist","description":"Retire un blacklist (réautorise l'appariement avec ce user).","operationId":"retirer_blacklist_api_v1_blacklists__target_user_id__delete","parameters":[{"name":"target_user_id","in":"path","required":true,"schema":{"type":"integer","title":"Target User Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/blacklists/me":{"get":{"tags":["blacklists"],"summary":"Mes Blacklists","description":"Liste des utilisateurs que J'AI blacklistés (avec raison + date).","operationId":"mes_blacklists_api_v1_blacklists_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/blacklists/check/{target_user_id}":{"get":{"tags":["blacklists"],"summary":"Check Blacklist Mutuel","description":"Vérifie si l'utilisateur courant est en blacklist (dans un sens ou l'autre)\navec le user cible. Utile pour l'app pour afficher un avertissement avant\nde proposer une course.","operationId":"check_blacklist_mutuel_api_v1_blacklists_check__target_user_id__get","parameters":[{"name":"target_user_id","in":"path","required":true,"schema":{"type":"integer","title":"Target User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/preferes/chauffeurs":{"get":{"tags":["preferes"],"summary":"Mes Chauffeurs Pref","description":"Liste de mes chauffeurs préférentiels (avec leur statut actuel).","operationId":"mes_chauffeurs_pref_api_v1_preferes_chauffeurs_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["preferes"],"summary":"Ajouter Chauffeur Pref","description":"Ajoute un chauffeur à mes préférentiels (max 3, ordre 1-3).","operationId":"ajouter_chauffeur_pref_api_v1_preferes_chauffeurs_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChauffeurPrefIn"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/preferes/chauffeurs/{chauffeur_id}":{"delete":{"tags":["preferes"],"summary":"Retirer Chauffeur Pref","operationId":"retirer_chauffeur_pref_api_v1_preferes_chauffeurs__chauffeur_id__delete","parameters":[{"name":"chauffeur_id","in":"path","required":true,"schema":{"type":"integer","title":"Chauffeur Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["preferes"],"summary":"Modifier Chauffeur Pref","description":"Modifier l'ordre ou le surnom d'un chauffeur pref.","operationId":"modifier_chauffeur_pref_api_v1_preferes_chauffeurs__chauffeur_id__patch","parameters":[{"name":"chauffeur_id","in":"path","required":true,"schema":{"type":"integer","title":"Chauffeur Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChauffeurPrefUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/preferes/passagers":{"get":{"tags":["preferes"],"summary":"Mes Passagers Pref","description":"Liste de mes passagers préférentiels.","operationId":"mes_passagers_pref_api_v1_preferes_passagers_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["preferes"],"summary":"Ajouter Passager Pref","description":"Le chauffeur ajoute un passager à ses préférentiels (sans limite).","operationId":"ajouter_passager_pref_api_v1_preferes_passagers_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PassagerPrefIn"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/preferes/passagers/{passager_id}":{"delete":{"tags":["preferes"],"summary":"Retirer Passager Pref","operationId":"retirer_passager_pref_api_v1_preferes_passagers__passager_id__delete","parameters":[{"name":"passager_id","in":"path","required":true,"schema":{"type":"integer","title":"Passager Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["preferes"],"summary":"Modifier Passager Pref","operationId":"modifier_passager_pref_api_v1_preferes_passagers__passager_id__patch","parameters":[{"name":"passager_id","in":"path","required":true,"schema":{"type":"integer","title":"Passager Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PassagerPrefUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/maps/autocomplete":{"get":{"tags":["maps"],"summary":"Autocomplete","description":"Suggestion d'adresses Google Places pour le passager.\nFiltré par pays (default 'ci'). Retourne max 5 suggestions.\nCoût : ~0.0028$ par requête (gratuit < 50 000/mois en Pay-as-you-go).","operationId":"autocomplete_api_v1_maps_autocomplete_get","parameters":[{"name":"input","in":"query","required":true,"schema":{"type":"string","minLength":2,"maxLength":200,"title":"Input"}},{"name":"country","in":"query","required":false,"schema":{"type":"string","minLength":2,"maxLength":2,"default":"ci","title":"Country"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/maps/place-details":{"get":{"tags":["maps"],"summary":"Place Details","description":"Convertit un place_id en coordonnées GPS + adresse formatée.","operationId":"place_details_api_v1_maps_place_details_get","parameters":[{"name":"place_id","in":"query","required":true,"schema":{"type":"string","description":"Place ID Google retourné par /autocomplete","title":"Place Id"},"description":"Place ID Google retourné par /autocomplete"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/maps/estimation":{"get":{"tags":["maps"],"summary":"Estimation","description":"Estime le prix d'une course AVANT de la créer.\nCalcule distance + durée via Google Distance Matrix, applique\nle barème de la ville la plus proche, retourne fourchette min-max.","operationId":"estimation_api_v1_maps_estimation_get","parameters":[{"name":"depart_lat","in":"query","required":true,"schema":{"type":"number","maximum":90,"minimum":-90,"title":"Depart Lat"}},{"name":"depart_lon","in":"query","required":true,"schema":{"type":"number","maximum":180,"minimum":-180,"title":"Depart Lon"}},{"name":"arrivee_lat","in":"query","required":true,"schema":{"type":"number","maximum":90,"minimum":-90,"title":"Arrivee Lat"}},{"name":"arrivee_lon","in":"query","required":true,"schema":{"type":"number","maximum":180,"minimum":-180,"title":"Arrivee Lon"}},{"name":"pays_code","in":"query","required":false,"schema":{"type":"string","minLength":2,"maxLength":2,"default":"CI","title":"Pays Code"}},{"name":"aller_retour","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Aller Retour"}},{"name":"duree_attente_min","in":"query","required":false,"schema":{"type":"integer","maximum":720,"minimum":0,"default":0,"title":"Duree Attente Min"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/maps/itineraires":{"get":{"tags":["maps"],"summary":"Itineraires","description":"Retourne plusieurs itineraires possibles (avec/sans peage).\nLe passager choisit en connaissance de cause. Tarifs peages lus dans la table peages.\n\nDetection peage : decode polyline + verifie proximite (<300m) avec un peage\nde la table 'peages' (catalogue dynamique gere par admin).\n\nRetour : { itineraires: [{summary, distance_km, duree_min, peage_estime_xof,\n          peages_traverses, total_estime_xof, polyline, has_toll, warnings}] }","operationId":"itineraires_api_v1_maps_itineraires_get","parameters":[{"name":"depart_lat","in":"query","required":true,"schema":{"type":"number","maximum":90,"minimum":-90,"title":"Depart Lat"}},{"name":"depart_lon","in":"query","required":true,"schema":{"type":"number","maximum":180,"minimum":-180,"title":"Depart Lon"}},{"name":"arrivee_lat","in":"query","required":true,"schema":{"type":"number","maximum":90,"minimum":-90,"title":"Arrivee Lat"}},{"name":"arrivee_lon","in":"query","required":true,"schema":{"type":"number","maximum":180,"minimum":-180,"title":"Arrivee Lon"}},{"name":"pays_code","in":"query","required":false,"schema":{"type":"string","minLength":2,"maxLength":2,"default":"CI","title":"Pays Code"}},{"name":"type_vehicule","in":"query","required":false,"schema":{"type":"string","default":"voiture","title":"Type Vehicule"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/maps/adresses-favorites":{"get":{"tags":["maps"],"summary":"Mes Adresses Favorites","operationId":"mes_adresses_favorites_api_v1_maps_adresses_favorites_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["maps"],"summary":"Ajouter Adresse Favorite","description":"Ajouter une adresse favorite ('Maison', 'Bureau', 'École enfants', etc.).","operationId":"ajouter_adresse_favorite_api_v1_maps_adresses_favorites_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdresseFavoriteIn"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/maps/adresses-favorites/{id}":{"delete":{"tags":["maps"],"summary":"Supprimer Adresse Favorite","operationId":"supprimer_adresse_favorite_api_v1_maps_adresses_favorites__id__delete","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","title":"Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/signalements":{"post":{"tags":["signalements"],"summary":"Creer Signalement","description":"Crée un signalement contre un autre utilisateur.\nGravité auto-calculée selon catégorie (ex: vol=5, no_show=2).\nSi gravité >= 4 → notification admin temps réel.","operationId":"creer_signalement_api_v1_signalements_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignalementIn"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/signalements/me/envoyes":{"get":{"tags":["signalements"],"summary":"Mes Signalements Envoyes","description":"Mes signalements envoyés.","operationId":"mes_signalements_envoyes_api_v1_signalements_me_envoyes_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/signalements/me/recus":{"get":{"tags":["signalements"],"summary":"Mes Signalements Recus","description":"Signalements RECUS contre moi (transparence — je vois ce qu'on me reproche).","operationId":"mes_signalements_recus_api_v1_signalements_me_recus_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/signalements/{id}":{"get":{"tags":["signalements"],"summary":"Detail Signalement","description":"Détail d'un signalement (auteur ou cible uniquement).","operationId":"detail_signalement_api_v1_signalements__id__get","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","title":"Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/share/courses/{course_id}":{"post":{"tags":["share"],"summary":"Creer Partage","description":"Génère un token de partage pour une course en cours.\nLe token expire à la fin de la course (ou 4h max).\nLe passager seul peut générer (ou un admin).","operationId":"creer_partage_api_v1_share_courses__course_id__post","parameters":[{"name":"course_id","in":"path","required":true,"schema":{"type":"string","title":"Course Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["share"],"summary":"Revoquer Partage","description":"Révoque tous les tokens de partage d'une course (le passager change d'avis).","operationId":"revoquer_partage_api_v1_share_courses__course_id__delete","parameters":[{"name":"course_id","in":"path","required":true,"schema":{"type":"string","title":"Course Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/share/{token}":{"get":{"tags":["share"],"summary":"Consulter Partage","description":"PUBLIC — affiche les infos de la course en direct (sans auth).\nLe destinataire du lien (proche du passager) appelle cet endpoint\npériodiquement pour suivre la position en temps réel.","operationId":"consulter_partage_api_v1_share__token__get","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/fcm/register-token":{"post":{"tags":["fcm"],"summary":"Register Fcm Token","description":"L'app mobile enregistre son FCM token.\nSi le user a déjà ce token enregistré → on met à jour `derniere_utilisation_at`.\nSinon on l'insère.","operationId":"register_fcm_token_api_v1_fcm_register_token_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FcmTokenIn"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/fcm/token":{"delete":{"tags":["fcm"],"summary":"Delete Fcm Token","description":"Supprime un token (déconnexion app).","operationId":"delete_fcm_token_api_v1_fcm_token_delete","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FcmTokenDelete"}}},"required":true},"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/fcm/my-tokens":{"get":{"tags":["fcm"],"summary":"My Tokens","description":"Mes tokens actifs (debug).","operationId":"my_tokens_api_v1_fcm_my_tokens_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/kyc/upload":{"post":{"tags":["kyc"],"summary":"Upload Document","description":"Upload d'un document KYC (chauffeur ou véhicule).\nLe fichier est stocké sur Cloudflare R2 (privé), seule l'URL S3 est gardée en DB.\nPour afficher : passer par /kyc/admin/{user_id} qui génère une URL signée 5 min.","operationId":"upload_document_api_v1_kyc_upload_post","parameters":[{"name":"type","in":"query","required":true,"schema":{"type":"string","description":"Type de document (selfie, cni_recto, etc.)","title":"Type"},"description":"Type de document (selfie, cni_recto, etc.)"},{"name":"vehicule_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Si type est un doc véhicule","title":"Vehicule Id"},"description":"Si type est un doc véhicule"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_document_api_v1_kyc_upload_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/kyc/me/statut":{"get":{"tags":["kyc"],"summary":"Mon Statut Kyc","description":"Mon état KYC (quels docs uploadés, lesquels manquent, statut global).","operationId":"mon_statut_kyc_api_v1_kyc_me_statut_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/kyc/me/soumettre":{"post":{"tags":["kyc"],"summary":"Soumettre Pour Validation","description":"Soumet le dossier KYC pour validation admin.\nVérifie d'abord que tous les documents obligatoires sont uploadés.\nStatut user passe de 'non_soumis' → 'soumis', impossible de modifier les\ndocuments jusqu'à validation/rejet par l'admin.","operationId":"soumettre_pour_validation_api_v1_kyc_me_soumettre_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/kyc/admin/pending":{"get":{"tags":["kyc"],"summary":"Admin Kyc Pending","description":"Liste des chauffeurs en attente de validation KYC. Auth: header X-Admin-Password.","operationId":"admin_kyc_pending_api_v1_kyc_admin_pending_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/kyc/admin/{target_user_id}":{"get":{"tags":["kyc"],"summary":"Admin Kyc Detail","description":"Détail KYC d'un chauffeur avec URLs signées (5 min) pour visualiser les documents.","operationId":"admin_kyc_detail_api_v1_kyc_admin__target_user_id__get","parameters":[{"name":"target_user_id","in":"path","required":true,"schema":{"type":"integer","title":"Target User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/kyc/admin/{target_user_id}/valider":{"post":{"tags":["kyc"],"summary":"Admin Valider","description":"Valide le KYC d'un chauffeur. Statut user passe à 'valide', expiration 1 an.\nLe chauffeur passe automatiquement de 'verification' à 'actif' (peut prendre des courses).","operationId":"admin_valider_api_v1_kyc_admin__target_user_id__valider_post","parameters":[{"name":"target_user_id","in":"path","required":true,"schema":{"type":"integer","title":"Target User Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValiderKYCIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/kyc/admin/{target_user_id}/rejeter":{"post":{"tags":["kyc"],"summary":"Admin Rejeter","description":"Rejette le KYC avec une raison. Le chauffeur peut re-soumettre après corrections.","operationId":"admin_rejeter_api_v1_kyc_admin__target_user_id__rejeter_post","parameters":[{"name":"target_user_id","in":"path","required":true,"schema":{"type":"integer","title":"Target User Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RejeterKYCIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/chauffeur/rentrer-chez-moi/activer":{"post":{"tags":["rentrer-chez-moi"],"summary":"Activer Rentrer Chez Moi","description":"Active le mode \"rentrer chez moi\" : à partir de maintenant, le chauffeur\nne reçoit que les courses qui le rapprochent de sa destination.\n\nPour désactiver : DELETE /rentrer-chez-moi","operationId":"activer_rentrer_chez_moi_api_v1_chauffeur_rentrer_chez_moi_activer_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RentrerChezMoiActiverIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/chauffeur/rentrer-chez-moi":{"get":{"tags":["rentrer-chez-moi"],"summary":"Etat Rentrer Chez Moi","description":"État actuel du mode.","operationId":"etat_rentrer_chez_moi_api_v1_chauffeur_rentrer_chez_moi_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"delete":{"tags":["rentrer-chez-moi"],"summary":"Desactiver Rentrer Chez Moi","description":"Désactive le mode.","operationId":"desactiver_rentrer_chez_moi_api_v1_chauffeur_rentrer_chez_moi_delete","responses":{"204":{"description":"Successful Response"}}}},"/api/v1/reservations":{"post":{"tags":["reservations"],"summary":"Creer Reservation","description":"Crée une réservation à l'avance. Le système la traitera automatiquement :\n- J-1 : rappel push au passager\n- H-30min : ré-ouvre la demande pour ring search ou attribution au pré-assigné","operationId":"creer_reservation_api_v1_reservations_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReservationIn"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/reservations/me":{"get":{"tags":["reservations"],"summary":"Mes Reservations","description":"Mes réservations à venir.","operationId":"mes_reservations_api_v1_reservations_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/reservations/{demande_id}":{"get":{"tags":["reservations"],"summary":"Detail Reservation","description":"Détail d'une réservation.","operationId":"detail_reservation_api_v1_reservations__demande_id__get","parameters":[{"name":"demande_id","in":"path","required":true,"schema":{"type":"integer","title":"Demande Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["reservations"],"summary":"Annuler Reservation","description":"Annule une réservation (avant qu'elle ne soit re-ouverte).","operationId":"annuler_reservation_api_v1_reservations__demande_id__delete","parameters":[{"name":"demande_id","in":"path","required":true,"schema":{"type":"integer","title":"Demande Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/support/chat":{"post":{"tags":["support"],"summary":"Chat Avec Ia","description":"Envoie un message au support IA Claude.\nSi ticket_id fourni : continue le ticket. Sinon : crée un nouveau ticket.","operationId":"chat_avec_ia_api_v1_support_chat_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/support/{ticket_id}/escalader":{"post":{"tags":["support"],"summary":"Escalader Ticket","description":"L'utilisateur escalade vers un humain (Honoré).","operationId":"escalader_ticket_api_v1_support__ticket_id__escalader_post","parameters":[{"name":"ticket_id","in":"path","required":true,"schema":{"type":"integer","title":"Ticket Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EscaladerIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/support/tickets/me":{"get":{"tags":["support"],"summary":"Mes Tickets","description":"Mes tickets de support.","operationId":"mes_tickets_api_v1_support_tickets_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/support/tickets/{ticket_id}/messages":{"get":{"tags":["support"],"summary":"Messages Ticket","description":"Historique conversation d'un ticket.","operationId":"messages_ticket_api_v1_support_tickets__ticket_id__messages_get","parameters":[{"name":"ticket_id","in":"path","required":true,"schema":{"type":"integer","title":"Ticket Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/support/{ticket_id}/satisfaction":{"post":{"tags":["support"],"summary":"Noter Support","description":"Note la qualité du support (1-5).","operationId":"noter_support_api_v1_support__ticket_id__satisfaction_post","parameters":[{"name":"ticket_id","in":"path","required":true,"schema":{"type":"integer","title":"Ticket Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SatisfactionIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/support/admin/escalades":{"get":{"tags":["support"],"summary":"Admin Tickets Escalades","description":"Tickets escaladés en attente de réponse humaine.","operationId":"admin_tickets_escalades_api_v1_support_admin_escalades_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/support/admin/{ticket_id}/repondre":{"post":{"tags":["support"],"summary":"Admin Repondre","description":"Réponse humaine (Honoré) à un ticket escaladé.","operationId":"admin_repondre_api_v1_support_admin__ticket_id__repondre_post","parameters":[{"name":"ticket_id","in":"path","required":true,"schema":{"type":"integer","title":"Ticket Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminRepondreIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/support/admin/{ticket_id}/clore":{"post":{"tags":["support"],"summary":"Admin Clore","description":"Clos le ticket après résolution.","operationId":"admin_clore_api_v1_support_admin__ticket_id__clore_post","parameters":[{"name":"ticket_id","in":"path","required":true,"schema":{"type":"integer","title":"Ticket Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/support/admin/cout-jour":{"get":{"tags":["support"],"summary":"Admin Cout Par Jour","description":"Coût IA jour par jour (90 derniers jours).","operationId":"admin_cout_par_jour_api_v1_support_admin_cout_jour_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/support/chat-vocal":{"post":{"tags":["support"],"summary":"Chat Vocal","description":"Pipeline vocal complet pour conversation avec Akwaba support :\n1. Reçoit audio user (multipart upload)\n2. Stocke audio user sur R2 (privé)\n3. STT → texte\n4. Récupère/crée ticket + charge historique\n5. Envoie au modèle Claude Haiku\n6. TTS → audio réponse\n7. Stocke audio réponse sur R2\n8. Retourne URLs signées 1h + texte + coûts\n\nCoût typique : ~25 FCFA / conversation (Studio voice).","operationId":"chat_vocal_api_v1_support_chat_vocal_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_chat_vocal_api_v1_support_chat_vocal_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/support/chat-vocal/{ticket_id}/tick-minute":{"post":{"tags":["support"],"summary":"Vocal Tick Minute","description":"Appelé par le client mobile chaque 60 sec après 3 min écoulées.\nDébite 100 FCFA du wallet et retourne le solde + numéro de minute.\nLe client coupe l'appel si solde épuisé (debit_xof = 0, minute_num = -1).","operationId":"vocal_tick_minute_api_v1_support_chat_vocal__ticket_id__tick_minute_post","parameters":[{"name":"ticket_id","in":"path","required":true,"schema":{"type":"integer","title":"Ticket Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/support/chat-vocal/{ticket_id}/terminer":{"post":{"tags":["support"],"summary":"Vocal Terminer","description":"Marque l'appel comme terminé, enregistre la durée totale.","operationId":"vocal_terminer_api_v1_support_chat_vocal__ticket_id__terminer_post","parameters":[{"name":"ticket_id","in":"path","required":true,"schema":{"type":"integer","title":"Ticket Id"}}],"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_vocal_terminer_api_v1_support_chat_vocal__ticket_id__terminer_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/monitoring/admin/dashboard":{"get":{"tags":["monitoring"],"summary":"Dashboard","description":"Stats globales temps réel — 1 seul appel.","operationId":"dashboard_api_v1_monitoring_admin_dashboard_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/monitoring/admin/chauffeurs":{"get":{"tags":["monitoring"],"summary":"Chauffeurs Positions","description":"Positions de tous les chauffeurs online (pour heatmap admin).","operationId":"chauffeurs_positions_api_v1_monitoring_admin_chauffeurs_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/monitoring/admin/courses-actives":{"get":{"tags":["monitoring"],"summary":"Courses Actives","description":"Courses actuellement en cours.","operationId":"courses_actives_api_v1_monitoring_admin_courses_actives_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/monitoring/admin/revenus":{"get":{"tags":["monitoring"],"summary":"Revenus Par Periode","description":"Revenus jour/semaine/mois + comparaison vs période précédente.","operationId":"revenus_par_periode_api_v1_monitoring_admin_revenus_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/monitoring/admin/top-chauffeurs":{"get":{"tags":["monitoring"],"summary":"Top Chauffeurs","description":"Top N chauffeurs par revenus sur une période.","operationId":"top_chauffeurs_api_v1_monitoring_admin_top_chauffeurs_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":10,"title":"Limit"}},{"name":"periode","in":"query","required":false,"schema":{"type":"string","default":"month","title":"Periode"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/support/vocal/solde":{"get":{"tags":["credits-vocal"],"summary":"Mon Solde","description":"Mon wallet vocal en FCFA. Tarif universel : 200 F le ticket d'entrée.","operationId":"mon_solde_api_v1_support_vocal_solde_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/support/vocal/info":{"get":{"tags":["credits-vocal"],"summary":"Info Pre Appel","description":"Info à afficher AVANT chaque appel vocal :\n- Tarification (ticket entrée 200 F + 100 F/min après 3 min)\n- Dispo 24/7\n- Solde wallet courant\n- Packs disponibles si solde insuffisant\n\nDécision business 2026-05-06 : tarif universel, aucune gratuité.\nLes urgences sont marquées en audit mais facturées au tarif normal.","operationId":"info_pre_appel_api_v1_support_vocal_info_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/support/vocal/packs":{"get":{"tags":["credits-vocal"],"summary":"List Packs","description":"Liste des packs disponibles à l'achat.","operationId":"list_packs_api_v1_support_vocal_packs_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/support/vocal/acheter":{"post":{"tags":["credits-vocal"],"summary":"Acheter Credits","description":"Achète un pack de crédits vocaux via mobile money (PayTech).\nGénère un payment_intent que le user paie sur son téléphone.\nLe webhook PayTech crédite ensuite automatiquement le compte.","operationId":"acheter_credits_api_v1_support_vocal_acheter_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcheterPackIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/support/vocal/webhook-paytech":{"post":{"tags":["credits-vocal"],"summary":"Webhook Paytech Vocal","description":"IPN PayTech : appelé quand un paiement de pack vocal est validé.\nCrédite automatiquement le wallet du user via crediter_wallet_vocal().\nDoit vérifier la signature HMAC PayTech avant de créditer.","operationId":"webhook_paytech_vocal_api_v1_support_vocal_webhook_paytech_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/support/vocal/historique":{"get":{"tags":["credits-vocal"],"summary":"Historique Credits","description":"Historique de mes transactions (achats + consommations).","operationId":"historique_credits_api_v1_support_vocal_historique_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/chauffeurs/{user_id}/valider":{"post":{"tags":["admin"],"summary":"Valider Chauffeur","operationId":"valider_chauffeur_api_v1_admin_chauffeurs__user_id__valider_post","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/chauffeurs/{user_id}/suspendre":{"post":{"tags":["admin"],"summary":"Suspendre Chauffeur","operationId":"suspendre_chauffeur_api_v1_admin_chauffeurs__user_id__suspendre_post","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/documents/{doc_id}/valider":{"post":{"tags":["admin"],"summary":"Valider Document","operationId":"valider_document_api_v1_admin_documents__doc_id__valider_post","parameters":[{"name":"doc_id","in":"path","required":true,"schema":{"type":"integer","title":"Doc Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/users/{user_id}/kyc-valider":{"post":{"tags":["admin"],"summary":"Valider Kyc","operationId":"valider_kyc_api_v1_admin_users__user_id__kyc_valider_post","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/chauffeurs/en-attente":{"get":{"tags":["admin"],"summary":"Chauffeurs En Attente","description":"Liste des chauffeurs en attente de validation.","operationId":"chauffeurs_en_attente_api_v1_admin_chauffeurs_en_attente_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/admin/chauffeurs":{"get":{"tags":["admin"],"summary":"List All Chauffeurs","description":"Liste tous les chauffeurs avec filtres optionnels.\n\nParams :\n- statut : 'actif' | 'verification' | 'suspendu' | None (tous)\n- q : recherche sur téléphone, prénoms, nom, pseudo_public, code09\n- limit, offset : pagination","operationId":"list_all_chauffeurs_api_v1_admin_chauffeurs_get","parameters":[{"name":"statut","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Statut"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Q"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/chauffeurs/{user_id}/historique":{"get":{"tags":["admin"],"summary":"Chauffeur Historique","description":"Historique des dernières courses d'un chauffeur (pour vue admin).","operationId":"chauffeur_historique_api_v1_admin_chauffeurs__user_id__historique_get","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/chauffeurs/{user_id}/reactiver":{"post":{"tags":["admin"],"summary":"Reactiver Chauffeur","description":"Réactive un chauffeur précédemment suspendu.","operationId":"reactiver_chauffeur_api_v1_admin_chauffeurs__user_id__reactiver_post","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/courses":{"get":{"tags":["admin"],"summary":"List All Courses","description":"Liste toutes les courses avec filtres optionnels.\n\nParams :\n- statut : 'en_attente' | 'acceptee' | 'en_cours' | 'terminee' | 'annulee' | None (tous)\n          Peut etre une liste comma-separated : 'en_cours,acceptee'\n- depuis : ISO date 'YYYY-MM-DD' (filtre debut_at >= depuis)\n- jusqu_a : ISO date 'YYYY-MM-DD' (filtre debut_at < jusqu_a + 1 jour)\n- q : recherche sur prenoms chauffeur, prenoms passager, code09, ID partiel, adresses\n- limit, offset : pagination (defaut 50)\n\nRetour : { total, limit, offset, items: [...] }","operationId":"list_all_courses_api_v1_admin_courses_get","parameters":[{"name":"statut","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Statut"}},{"name":"depuis","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Depuis"}},{"name":"jusqu_a","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Jusqu A"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Q"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/courses/{course_id}":{"get":{"tags":["admin"],"summary":"Detail Course","description":"Detail complet d une course.","operationId":"detail_course_api_v1_admin_courses__course_id__get","parameters":[{"name":"course_id","in":"path","required":true,"schema":{"type":"string","title":"Course Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/stats":{"get":{"tags":["admin"],"summary":"Stats Globales","description":"Dashboard admin global.","operationId":"stats_globales_api_v1_admin_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/admin/sos-actives":{"get":{"tags":["admin"],"summary":"List Sos Actives","operationId":"list_sos_actives_api_v1_admin_sos_actives_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/admin/sos/{alerte_id}/resoudre":{"post":{"tags":["admin"],"summary":"Resoudre Sos","operationId":"resoudre_sos_api_v1_admin_sos__alerte_id__resoudre_post","parameters":[{"name":"alerte_id","in":"path","required":true,"schema":{"type":"integer","title":"Alerte Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/peages":{"get":{"tags":["admin"],"summary":"List Peages","description":"Liste les peages (par pays optionnel).","operationId":"list_peages_api_v1_admin_peages_get","parameters":[{"name":"pays_code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pays Code"}},{"name":"actif_seulement","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Actif Seulement"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["admin"],"summary":"Create Peage","description":"Cree un nouveau peage.","operationId":"create_peage_api_v1_admin_peages_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PeageIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/peages/{peage_id}":{"put":{"tags":["admin"],"summary":"Update Peage","description":"Met a jour un peage existant.","operationId":"update_peage_api_v1_admin_peages__peage_id__put","parameters":[{"name":"peage_id","in":"path","required":true,"schema":{"type":"integer","title":"Peage Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PeageIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["admin"],"summary":"Delete Peage","description":"Suppression douce : marque actif=FALSE plutot que delete physique.","operationId":"delete_peage_api_v1_admin_peages__peage_id__delete","parameters":[{"name":"peage_id","in":"path","required":true,"schema":{"type":"integer","title":"Peage Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/arrets-reroutes":{"get":{"tags":["admin"],"summary":"List Arrets Reroutes","description":"Liste arrets dynamiques + reroutes des N derniers jours.\nUtile pour deceler les abus (chauffeurs refusant systematiquement,\npassagers spammant des changements).\n\nParams :\n- jours : nombre de jours en arriere (defaut 30)\n- statut : filtre optionnel ('propose'|'accepte'|'refuse'|'reparti'|'annule'|...)","operationId":"list_arrets_reroutes_api_v1_admin_arrets_reroutes_get","parameters":[{"name":"jours","in":"query","required":false,"schema":{"type":"integer","default":30,"title":"Jours"}},{"name":"statut","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Statut"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/":{"get":{"summary":"Root","operationId":"root__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/health":{"get":{"summary":"Health","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/health/maps":{"get":{"summary":"Health Maps","description":"Smoke test Google Maps + Weather.","operationId":"health_maps_health_maps_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/reports":{"post":{"tags":["reports"],"summary":"Signaler","description":"Crée un signalement avec score initial 1, statut 'non_valide'.\nDevient 'valide' après 2 confirmations indépendantes (score >= 3).\n\nGarde-fous (migration 029) :\n  - Max 5 signalements / 24h / user\n  - Distance min 200m entre 2 signalements du même user (30 min)\n  - Pas de signalement < 50m d'un radar fixe (info redondante)\n  - Bannissement auto si > 10 reports refutés en 7 jours","operationId":"signaler_api_v1_reports_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportIn"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/reports/{report_id}/vote":{"post":{"tags":["reports"],"summary":"Voter","description":"Vote pondéré sur un report :\n  - User fiable (>=80) : poids 2\n  - User normal (>=30) : poids 1\n  - User suspect (<30) : poids 0 (vote ignoré, mais audité)\n\nScore transitions :\n  - score >= 3  → statut 'valide'  (info confirmée)\n  - score <= -2 → statut 'refute'  (info rejetée)\n\nConfirm prolonge expires_at de +15 min.\nRefuter peut entraîner un bannissement auto du créateur (10/7j).","operationId":"voter_api_v1_reports__report_id__vote_post","parameters":[{"name":"report_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Report Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoteIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/reports/zone":{"get":{"tags":["reports"],"summary":"Reports Dans Zone","description":"Liste tous les signalements actifs (non expirés) dans un rayon.\nInclut radars fixes ET reports crowdsourcés.\n\nLe client peut filtrer côté UI selon le statut :\n  - 'valide' (score >= 3) → afficher rouge, info confirmée\n  - 'non_valide' (1-2 votes) → afficher orange, à prendre avec réserve","operationId":"reports_dans_zone_api_v1_reports_zone_get","parameters":[{"name":"lat","in":"query","required":true,"schema":{"type":"number","maximum":90,"minimum":-90,"title":"Lat"}},{"name":"lon","in":"query","required":true,"schema":{"type":"number","maximum":180,"minimum":-180,"title":"Lon"}},{"name":"rayon_m","in":"query","required":false,"schema":{"type":"integer","maximum":20000,"minimum":100,"default":2000,"title":"Rayon M"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/reports/me/recents":{"get":{"tags":["reports"],"summary":"Mes Reports Recents","description":"Mes derniers signalements avec leur état actuel.","operationId":"mes_reports_recents_api_v1_reports_me_recents_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/reports/me/fiabilite":{"get":{"tags":["reports"],"summary":"Ma Fiabilite Reports","description":"Ma fiabilité actuelle (0-100) + bannissement éventuel.","operationId":"ma_fiabilite_reports_api_v1_reports_me_fiabilite_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/score/me":{"get":{"tags":["extras"],"summary":"Mon Score","description":"Mon tier actuel + progression visuelle vers le suivant.","operationId":"mon_score_api_v1_score_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/score/{chauffeur_id}":{"get":{"tags":["extras"],"summary":"Score Public","description":"Score d'un chauffeur (visible à tout user pour info passager).","operationId":"score_public_api_v1_score__chauffeur_id__get","parameters":[{"name":"chauffeur_id","in":"path","required":true,"schema":{"type":"integer","title":"Chauffeur Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/courses/{course_id}/pourboire":{"post":{"tags":["extras"],"summary":"Ajouter Pourboire","description":"Le passager ajoute un pourboire à la fin de la course.\nLe chauffeur reçoit le montant en cash ou mobile money direct\n(Akwaba ne touche pas le flux financier).\nAkwaba enregistre juste pour audit/stats.","operationId":"ajouter_pourboire_api_v1_courses__course_id__pourboire_post","parameters":[{"name":"course_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Course Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PourboireIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/heatmap/demandes":{"get":{"tags":["extras"],"summary":"Heatmap Demandes","description":"Zones chaudes des demandes des 60 dernières minutes (grille 1km×1km).\nRéservée aux chauffeurs pour les guider vers la demande.\nSi lat/lon fournis : filtre dans un rayon. Sinon retourne tout.","operationId":"heatmap_demandes_api_v1_heatmap_demandes_get","parameters":[{"name":"lat","in":"query","required":false,"schema":{"anyOf":[{"type":"number","maximum":90,"minimum":-90},{"type":"null"}],"title":"Lat"}},{"name":"lon","in":"query","required":false,"schema":{"anyOf":[{"type":"number","maximum":180,"minimum":-180},{"type":"null"}],"title":"Lon"}},{"name":"rayon_km","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Rayon Km"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/evenements/actifs":{"get":{"tags":["extras"],"summary":"Evenements Actifs","description":"Événements pricing actifs aujourd'hui pour un pays.","operationId":"evenements_actifs_api_v1_evenements_actifs_get","parameters":[{"name":"pays_code","in":"query","required":false,"schema":{"type":"string","pattern":"^[A-Z]{2}$","default":"CI","title":"Pays Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/aeroport/forfait":{"get":{"tags":["sprint2"],"summary":"Devis Forfait Aeroport","description":"Cherche un forfait aéroport applicable au trajet demandé.\nSi aucun forfait ne match (ni au départ ni à l'arrivée d'un aéroport),\nle client doit utiliser le devis classique `/maps/estimation`.","operationId":"devis_forfait_aeroport_api_v1_aeroport_forfait_get","parameters":[{"name":"lat_depart","in":"query","required":true,"schema":{"type":"number","maximum":90,"minimum":-90,"title":"Lat Depart"}},{"name":"lon_depart","in":"query","required":true,"schema":{"type":"number","maximum":180,"minimum":-180,"title":"Lon Depart"}},{"name":"lat_arrivee","in":"query","required":true,"schema":{"type":"number","maximum":90,"minimum":-90,"title":"Lat Arrivee"}},{"name":"lon_arrivee","in":"query","required":true,"schema":{"type":"number","maximum":180,"minimum":-180,"title":"Lon Arrivee"}},{"name":"categorie","in":"query","required":false,"schema":{"type":"string","pattern":"^(voiture|moto|tricycle|bus)$","default":"voiture","title":"Categorie"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/recurrentes":{"post":{"tags":["sprint2"],"summary":"Creer Recurrente","description":"Crée une course récurrente (ex: tous les lundis 7h Cocody → Plateau).","operationId":"creer_recurrente_api_v1_recurrentes_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CourseRecurrenteIn"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/recurrentes/me":{"get":{"tags":["sprint2"],"summary":"Mes Recurrentes","operationId":"mes_recurrentes_api_v1_recurrentes_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/recurrentes/{rec_id}":{"delete":{"tags":["sprint2"],"summary":"Desactiver Recurrente","operationId":"desactiver_recurrente_api_v1_recurrentes__rec_id__delete","parameters":[{"name":"rec_id","in":"path","required":true,"schema":{"type":"integer","title":"Rec Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/qr/{token}":{"get":{"tags":["sprint2"],"summary":"Resolve Qr Token","description":"Endpoint PUBLIC (pas de JWT) — résout un QR code véhicule.\nPermet à un passager qui scanne le QR sur la portière d'un taxi\nde voir les infos du véhicule + chauffeur AVANT de monter.\nPas de données sensibles : juste les infos véhicule + note moyenne.","operationId":"resolve_qr_token_api_v1_qr__token__get","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/chauffeurs/me/qr":{"get":{"tags":["sprint2"],"summary":"Mon Qr Token","description":"Le chauffeur récupère son token QR pour l'imprimer.","operationId":"mon_qr_token_api_v1_chauffeurs_me_qr_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/admin/aeroport/forfaits":{"post":{"tags":["sprint2"],"summary":"Admin Creer Forfait","description":"Crée un nouveau forfait aéroport (admin only).","operationId":"admin_creer_forfait_api_v1_admin_aeroport_forfaits_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForfaitAdminIn"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/aeroport/forfaits/{forfait_id}/prix":{"put":{"tags":["sprint2"],"summary":"Admin Changer Prix Forfait","description":"Modifie le prix d'un forfait existant.","operationId":"admin_changer_prix_forfait_api_v1_admin_aeroport_forfaits__forfait_id__prix_put","parameters":[{"name":"forfait_id","in":"path","required":true,"schema":{"type":"integer","title":"Forfait Id"}},{"name":"nouveau_prix_xof","in":"query","required":true,"schema":{"type":"integer","maximum":100000,"minimum":1000,"title":"Nouveau Prix Xof"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/aeroport/forfaits/{forfait_id}":{"delete":{"tags":["sprint2"],"summary":"Admin Desactiver Forfait","description":"Désactive un forfait (soft delete : actif = FALSE).","operationId":"admin_desactiver_forfait_api_v1_admin_aeroport_forfaits__forfait_id__delete","parameters":[{"name":"forfait_id","in":"path","required":true,"schema":{"type":"integer","title":"Forfait Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/i18n/langues":{"get":{"tags":["sprint3"],"summary":"Langues Disponibles","description":"Liste publique des langues disponibles avec nombre de traductions.","operationId":"langues_disponibles_api_v1_i18n_langues_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/i18n/{langue}":{"get":{"tags":["sprint3"],"summary":"Traductions Par Langue","description":"Toutes les traductions d'une langue (consommé par l'app à chaque login).","operationId":"traductions_par_langue_api_v1_i18n__langue__get","parameters":[{"name":"langue","in":"path","required":true,"schema":{"type":"string","title":"Langue"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/i18n/me/langue":{"put":{"tags":["sprint3"],"summary":"Changer Ma Langue","operationId":"changer_ma_langue_api_v1_i18n_me_langue_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LangueIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/scolaire":{"post":{"tags":["sprint3"],"summary":"Souscrire Abonnement Scolaire","description":"Souscrit un abonnement scolaire mensuel avec chauffeur fixe.","operationId":"souscrire_abonnement_scolaire_api_v1_scolaire_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AbonnementScolaireIn"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/scolaire/me":{"get":{"tags":["sprint3"],"summary":"Mes Abonnements Scolaires","operationId":"mes_abonnements_scolaires_api_v1_scolaire_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/entreprises/me":{"get":{"tags":["sprint3"],"summary":"Mon Entreprise","description":"Si l'user est rattaché à une entreprise, retourne les infos + plafonds.","operationId":"mon_entreprise_api_v1_entreprises_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/entreprises/me/peut-facturer":{"get":{"tags":["sprint3"],"summary":"Puis Je Facturer","description":"Vérifie si la course peut être facturée à l'entreprise.","operationId":"puis_je_facturer_api_v1_entreprises_me_peut_facturer_get","parameters":[{"name":"montant_xof","in":"query","required":true,"schema":{"type":"integer","maximum":200000,"minimum":100,"title":"Montant Xof"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/pool/creer":{"post":{"tags":["sprint3"],"summary":"Creer Pool","description":"Le chauffeur ouvre un pool : 2-3 passagers même direction se partagent\nle prix réduit. Pool reste ouvert pendant fenetre_minutes puis se\nferme automatiquement (cron akwaba-pools-close).","operationId":"creer_pool_api_v1_pool_creer_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PoolCreerIn"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/pool/compatibles":{"get":{"tags":["sprint3"],"summary":"Trouver Pools","description":"Liste les pools en cours compatibles avec le trajet du passager.","operationId":"trouver_pools_api_v1_pool_compatibles_get","parameters":[{"name":"lat_dep","in":"query","required":true,"schema":{"type":"number","maximum":90,"minimum":-90,"title":"Lat Dep"}},{"name":"lon_dep","in":"query","required":true,"schema":{"type":"number","maximum":180,"minimum":-180,"title":"Lon Dep"}},{"name":"lat_arr","in":"query","required":true,"schema":{"type":"number","maximum":90,"minimum":-90,"title":"Lat Arr"}},{"name":"lon_arr","in":"query","required":true,"schema":{"type":"number","maximum":180,"minimum":-180,"title":"Lon Arr"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/pool/rejoindre":{"post":{"tags":["sprint3"],"summary":"Rejoindre Pool","description":"Rejoint un pool existant.","operationId":"rejoindre_pool_api_v1_pool_rejoindre_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PoolRejoindreIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"AbonnementScolaireIn":{"properties":{"chauffeur_fixe_id":{"type":"integer","title":"Chauffeur Fixe Id"},"enfant_prenoms":{"type":"string","maxLength":100,"title":"Enfant Prenoms"},"enfant_age":{"anyOf":[{"type":"integer","maximum":20.0,"minimum":2.0},{"type":"null"}],"title":"Enfant Age"},"ecole_nom":{"type":"string","maxLength":150,"title":"Ecole Nom"},"ecole_adresse":{"type":"string","title":"Ecole Adresse"},"ecole_lat":{"type":"number","title":"Ecole Lat"},"ecole_lon":{"type":"number","title":"Ecole Lon"},"domicile_adresse":{"type":"string","title":"Domicile Adresse"},"domicile_lat":{"type":"number","title":"Domicile Lat"},"domicile_lon":{"type":"number","title":"Domicile Lon"},"heure_aller":{"type":"string","pattern":"^\\d{2}:\\d{2}$","title":"Heure Aller"},"heure_retour":{"type":"string","pattern":"^\\d{2}:\\d{2}$","title":"Heure Retour"},"jours_actifs":{"items":{"type":"integer"},"type":"array","title":"Jours Actifs"},"prix_mensuel_xof":{"type":"integer","maximum":200000.0,"minimum":5000.0,"title":"Prix Mensuel Xof"},"note_specifique":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note Specifique"}},"type":"object","required":["chauffeur_fixe_id","enfant_prenoms","ecole_nom","ecole_adresse","ecole_lat","ecole_lon","domicile_adresse","domicile_lat","domicile_lon","heure_aller","heure_retour","prix_mensuel_xof"],"title":"AbonnementScolaireIn"},"AccepterAlerteIn":{"properties":{"multiplier":{"type":"number","maximum":5.0,"minimum":1.0,"title":"Multiplier"}},"type":"object","required":["multiplier"],"title":"AccepterAlerteIn"},"AcheterPackIn":{"properties":{"pack_code":{"type":"string","title":"Pack Code","description":"Code pack (w_200, w_1000, w_2000, w_5000, w_10000)"},"moyen_paiement":{"type":"string","pattern":"^(wave|orange|mtn|moov|free)$","title":"Moyen Paiement"},"msisdn":{"type":"string","title":"Msisdn","description":"Numéro mobile money (ex +22507xxxxxxxx)"}},"type":"object","required":["pack_code","moyen_paiement","msisdn"],"title":"AcheterPackIn"},"AdminRepondreIn":{"properties":{"contenu":{"type":"string","maxLength":2000,"minLength":2,"title":"Contenu"}},"type":"object","required":["contenu"],"title":"AdminRepondreIn"},"AdresseFavoriteIn":{"properties":{"label":{"type":"string","maxLength":80,"minLength":1,"title":"Label"},"adresse_texte":{"type":"string","maxLength":300,"minLength":2,"title":"Adresse Texte"},"lat":{"type":"number","maximum":90.0,"minimum":-90.0,"title":"Lat"},"lng":{"type":"number","maximum":180.0,"minimum":-180.0,"title":"Lng"},"place_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Place Id"},"icone":{"type":"string","maxLength":20,"title":"Icone","default":"pin"}},"type":"object","required":["label","adresse_texte","lat","lng"],"title":"AdresseFavoriteIn"},"AlerteOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"ville":{"type":"string","title":"Ville"},"quartier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Quartier"},"lat":{"type":"number","title":"Lat"},"lng":{"type":"number","title":"Lng"},"rayon_m":{"type":"integer","title":"Rayon M"},"type_alerte":{"type":"string","title":"Type Alerte"},"severite":{"type":"integer","title":"Severite"},"raisons":{"items":{},"type":"array","title":"Raisons"},"demande_active":{"type":"integer","title":"Demande Active"},"chauffeurs_dispo":{"type":"integer","title":"Chauffeurs Dispo"},"ratio_desequilibre":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Ratio Desequilibre"},"multiplier_min":{"type":"number","title":"Multiplier Min"},"multiplier_max":{"type":"number","title":"Multiplier Max"},"multiplier_suggere":{"type":"number","title":"Multiplier Suggere"},"meteo":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Meteo"},"secondes_restantes":{"type":"integer","title":"Secondes Restantes"},"distance_m":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Distance M","description":"Distance depuis la position du chauffeur (si appel /proche)"}},"type":"object","required":["id","ville","lat","lng","rayon_m","type_alerte","severite","raisons","demande_active","chauffeurs_dispo","multiplier_min","multiplier_max","multiplier_suggere","secondes_restantes"],"title":"AlerteOut"},"AnnulerIn":{"properties":{"raison":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Raison"}},"type":"object","title":"AnnulerIn"},"ArretIn":{"properties":{"lat":{"type":"number","maximum":90.0,"minimum":-90.0,"title":"Lat"},"lon":{"type":"number","maximum":180.0,"minimum":-180.0,"title":"Lon"},"adresse":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Adresse"},"duree_estimee_min":{"type":"integer","maximum":180.0,"minimum":1.0,"title":"Duree Estimee Min","default":5}},"type":"object","required":["lat","lon"],"title":"ArretIn"},"AuthInitIn":{"properties":{"telephone":{"type":"string","maxLength":20,"minLength":8,"title":"Telephone"},"pays_code":{"type":"string","maxLength":2,"minLength":2,"title":"Pays Code","default":"CI"}},"type":"object","required":["telephone"],"title":"AuthInitIn"},"AuthInitOut":{"properties":{"pending_token":{"type":"string","title":"Pending Token"},"expires_in_seconds":{"type":"integer","title":"Expires In Seconds"}},"type":"object","required":["pending_token","expires_in_seconds"],"title":"AuthInitOut"},"AuthVerifyIn":{"properties":{"pending_token":{"type":"string","title":"Pending Token"},"code":{"type":"string","maxLength":8,"minLength":4,"title":"Code"}},"type":"object","required":["pending_token","code"],"title":"AuthVerifyIn"},"AuthVerifyOut":{"properties":{"code09":{"type":"string","title":"Code09"},"jwt_token":{"type":"string","title":"Jwt Token"},"expires_at":{"type":"string","title":"Expires At"},"new_user":{"type":"boolean","title":"New User"}},"type":"object","required":["code09","jwt_token","expires_at","new_user"],"title":"AuthVerifyOut"},"BlacklistIn":{"properties":{"user_id":{"type":"integer","title":"User Id","description":"ID de l'utilisateur à blacklister"},"raison":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Raison"},"course_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Course Id","description":"Course qui a déclenché (optionnel)"}},"type":"object","required":["user_id"],"title":"BlacklistIn"},"Body_chat_vocal_api_v1_support_chat_vocal_post":{"properties":{"audio":{"type":"string","contentMediaType":"application/octet-stream","title":"Audio","description":"Fichier audio MP3/WAV/OGG du user"},"encoding":{"type":"string","title":"Encoding","description":"MP3, LINEAR16, OGG_OPUS, WEBM_OPUS, FLAC","default":"MP3"},"sample_rate":{"type":"integer","title":"Sample Rate","default":24000},"ticket_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Ticket Id"},"voix":{"type":"string","title":"Voix","default":"fr-FR-Studio-D"}},"type":"object","required":["audio"],"title":"Body_chat_vocal_api_v1_support_chat_vocal_post"},"Body_upload_document_api_v1_kyc_upload_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"}},"type":"object","required":["file"],"title":"Body_upload_document_api_v1_kyc_upload_post"},"Body_vocal_terminer_api_v1_support_chat_vocal__ticket_id__terminer_post":{"properties":{"duree_secondes":{"type":"integer","title":"Duree Secondes"}},"type":"object","required":["duree_secondes"],"title":"Body_vocal_terminer_api_v1_support_chat_vocal__ticket_id__terminer_post"},"ChatIn":{"properties":{"message":{"type":"string","maxLength":2000,"minLength":2,"title":"Message"},"ticket_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Ticket Id","description":"Continuer un ticket existant"},"course_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Course Id"}},"type":"object","required":["message"],"title":"ChatIn"},"ChauffeurPrefIn":{"properties":{"chauffeur_id":{"type":"integer","title":"Chauffeur Id"},"ordre_priorite":{"type":"integer","maximum":3.0,"minimum":1.0,"title":"Ordre Priorite"},"surnom":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Surnom"}},"type":"object","required":["chauffeur_id","ordre_priorite"],"title":"ChauffeurPrefIn"},"ChauffeurPrefUpdate":{"properties":{"ordre_priorite":{"anyOf":[{"type":"integer","maximum":3.0,"minimum":1.0},{"type":"null"}],"title":"Ordre Priorite"},"surnom":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Surnom"}},"type":"object","title":"ChauffeurPrefUpdate"},"CheckoutIn":{"properties":{"course_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Course Id"},"montant_xof":{"type":"integer","maximum":10000000.0,"minimum":100.0,"title":"Montant Xof"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"}},"type":"object","required":["montant_xof"],"title":"CheckoutIn"},"CodeColisIn":{"properties":{"code":{"type":"string","pattern":"^\\d{4}$","title":"Code","description":"Code 4 chiffres"}},"type":"object","required":["code"],"title":"CodeColisIn"},"CodeDemarrageIn":{"properties":{"code":{"type":"string","maxLength":4,"minLength":4,"pattern":"^[0-9]{4}$","title":"Code"}},"type":"object","required":["code"],"title":"CodeDemarrageIn"},"CommentIn":{"properties":{"contenu":{"type":"string","maxLength":2000,"minLength":1,"title":"Contenu"}},"type":"object","required":["contenu"],"title":"CommentIn"},"CourseEndIn":{"properties":{"arrivee_lat":{"type":"number","maximum":90.0,"minimum":-90.0,"title":"Arrivee Lat"},"arrivee_lon":{"type":"number","maximum":180.0,"minimum":-180.0,"title":"Arrivee Lon"},"arrivee_adresse":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Arrivee Adresse"},"distance_km":{"type":"number","minimum":0.0,"title":"Distance Km"},"montant_xof":{"type":"integer","minimum":0.0,"title":"Montant Xof"},"moyen_paiement":{"type":"string","title":"Moyen Paiement","default":"espece"},"paye":{"type":"boolean","title":"Paye","default":true}},"type":"object","required":["arrivee_lat","arrivee_lon","distance_km","montant_xof"],"title":"CourseEndIn"},"CourseRecurrenteIn":{"properties":{"libelle":{"type":"string","maxLength":100,"title":"Libelle"},"depart_lat":{"type":"number","maximum":90.0,"minimum":-90.0,"title":"Depart Lat"},"depart_lon":{"type":"number","maximum":180.0,"minimum":-180.0,"title":"Depart Lon"},"depart_adresse":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Depart Adresse"},"arrivee_lat":{"anyOf":[{"type":"number","maximum":90.0,"minimum":-90.0},{"type":"null"}],"title":"Arrivee Lat"},"arrivee_lon":{"anyOf":[{"type":"number","maximum":180.0,"minimum":-180.0},{"type":"null"}],"title":"Arrivee Lon"},"arrivee_adresse":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Arrivee Adresse"},"type_vehicule_demande":{"type":"string","pattern":"^(voiture|moto|tricycle|bus)$","title":"Type Vehicule Demande","default":"voiture"},"jours_semaine":{"items":{"type":"integer"},"type":"array","title":"Jours Semaine","description":"1=lundi ... 7=dimanche"},"heure_depart":{"type":"string","pattern":"^\\d{2}:\\d{2}$","title":"Heure Depart","description":"Heure HH:MM, ex 07:30"},"chauffeur_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Chauffeur Id"},"note_specifique":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note Specifique"}},"type":"object","required":["libelle","depart_lat","depart_lon","jours_semaine","heure_depart"],"title":"CourseRecurrenteIn"},"CourseStartWithDestIn":{"properties":{"passager_telephone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Passager Telephone"},"vehicule_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Vehicule Id"},"depart_lat":{"type":"number","maximum":90.0,"minimum":-90.0,"title":"Depart Lat"},"depart_lon":{"type":"number","maximum":180.0,"minimum":-180.0,"title":"Depart Lon"},"depart_adresse":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Depart Adresse"},"arrivee_lat":{"anyOf":[{"type":"number","maximum":90.0,"minimum":-90.0},{"type":"null"}],"title":"Arrivee Lat"},"arrivee_lon":{"anyOf":[{"type":"number","maximum":180.0,"minimum":-180.0},{"type":"null"}],"title":"Arrivee Lon"},"arrivee_adresse":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Arrivee Adresse"},"distance_km":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Distance Km"}},"type":"object","required":["depart_lat","depart_lon"],"title":"CourseStartWithDestIn"},"DemandeCourseIn":{"properties":{"depart_lat":{"type":"number","maximum":90.0,"minimum":-90.0,"title":"Depart Lat"},"depart_lon":{"type":"number","maximum":180.0,"minimum":-180.0,"title":"Depart Lon"},"depart_adresse":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Depart Adresse"},"arrivee_lat":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Arrivee Lat"},"arrivee_lon":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Arrivee Lon"},"arrivee_adresse":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Arrivee Adresse"},"distance_estimee_km":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Distance Estimee Km"},"type_demande":{"type":"string","pattern":"^(standard|urgent|colis|inter_ville|reservation)$","title":"Type Demande","default":"standard"},"type_vehicule_demande":{"type":"string","pattern":"^(voiture|moto|tricycle|bus|tout)$","title":"Type Vehicule Demande","description":"Catégorie de véhicule demandée (voiture/moto/tricycle/bus/tout)","default":"voiture"},"pour_quand":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Pour Quand"},"nb_passagers":{"type":"integer","title":"Nb Passagers","default":1},"note_specifique":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note Specifique"},"destinataire_telephone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Destinataire Telephone","description":"Téléphone du destinataire du colis (E.164, ex: +22507xxxxxxxx)"},"destinataire_nom":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Destinataire Nom","description":"Nom du destinataire du colis"},"colis_description":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Colis Description","description":"Description du colis (ex: 'Documents A4', 'Sac en tissu')"},"colis_taille":{"anyOf":[{"type":"string","pattern":"^(S|M|L|XL)$"},{"type":"null"}],"title":"Colis Taille","description":"S = enveloppe / M = sac à main / L = sac de marché / XL = carton"},"colis_fragile":{"type":"boolean","title":"Colis Fragile","default":false},"colis_valeur_xof":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Colis Valeur Xof","description":"Valeur déclarée du colis en FCFA (optionnel, info chauffeur)"},"mode_femme_rassuree":{"type":"boolean","title":"Mode Femme Rassuree","description":"Si TRUE, ring-search filtre uniquement les chauffeurs femmes OU les chauffeurs très bien notés (>=4.5/5 et >=50 courses). Différenciant Akwaba pour la sécurité des passagères.","default":false},"chauffeur_prefere_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Chauffeur Prefere Id","description":"Si renseigne, ce chauffeur est propose en priorite (preferentiel_chauffeur_id). Cas d'usage : 'Continuer avec ce chauffeur' apres une course terminee."}},"type":"object","required":["depart_lat","depart_lon"],"title":"DemandeCourseIn"},"DevisOut":{"properties":{"distance_km":{"type":"number","title":"Distance Km"},"duree_min":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Duree Min"},"ville_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Ville Id"},"ville_nom":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ville Nom"},"base_xof":{"type":"integer","title":"Base Xof"},"multiplier":{"type":"number","title":"Multiplier"},"suggere_xof":{"type":"integer","title":"Suggere Xof"},"breakdown":{"additionalProperties":true,"type":"object","title":"Breakdown"},"raison_multiplier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Raison Multiplier"}},"type":"object","required":["distance_km","duree_min","ville_id","ville_nom","base_xof","multiplier","suggere_xof","breakdown"],"title":"DevisOut","description":"Devis tarifaire pour une course (suggéré à partir du barème ville × multiplier surge)."},"DocumentIn":{"properties":{"type_document":{"type":"string","title":"Type Document"},"fichier_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fichier Url"},"numero":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Numero"},"emis_le":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Emis Le"},"expire_le":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Expire Le"}},"type":"object","required":["type_document"],"title":"DocumentIn"},"EscaladerIn":{"properties":{"raison":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Raison"}},"type":"object","title":"EscaladerIn"},"FcmTokenDelete":{"properties":{"token":{"type":"string","title":"Token"}},"type":"object","required":["token"],"title":"FcmTokenDelete"},"FcmTokenIn":{"properties":{"token":{"type":"string","maxLength":500,"minLength":20,"title":"Token"},"platform":{"type":"string","pattern":"^(android|ios|web)$","title":"Platform"},"device_info":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Device Info"}},"type":"object","required":["token","platform"],"title":"FcmTokenIn"},"ForfaitAdminIn":{"properties":{"aeroport_id":{"type":"integer","title":"Aeroport Id"},"zone_libelle":{"type":"string","maxLength":100,"title":"Zone Libelle"},"zone_centre_lat":{"type":"number","maximum":90.0,"minimum":-90.0,"title":"Zone Centre Lat"},"zone_centre_lon":{"type":"number","maximum":180.0,"minimum":-180.0,"title":"Zone Centre Lon"},"rayon_zone_m":{"type":"integer","maximum":10000.0,"minimum":200.0,"title":"Rayon Zone M","default":2000},"prix_xof":{"type":"integer","maximum":100000.0,"minimum":1000.0,"title":"Prix Xof"},"type_vehicule_categorie":{"type":"string","pattern":"^(voiture|moto|tricycle|bus|utilitaire)$","title":"Type Vehicule Categorie","default":"voiture"}},"type":"object","required":["aeroport_id","zone_libelle","zone_centre_lat","zone_centre_lon","prix_xof"],"title":"ForfaitAdminIn"},"FormationCompleteIn":{"properties":{"formation_id":{"type":"integer","title":"Formation Id"},"score":{"type":"integer","maximum":100.0,"minimum":0.0,"title":"Score"}},"type":"object","required":["formation_id","score"],"title":"FormationCompleteIn"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"IdentiteCivileIn":{"properties":{"nom":{"type":"string","maxLength":100,"minLength":1,"title":"Nom"},"prenoms":{"type":"string","maxLength":100,"minLength":1,"title":"Prenoms"},"sexe":{"anyOf":[{"type":"string","pattern":"^[HF]$"},{"type":"null"}],"title":"Sexe"},"lieu_naissance":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Lieu Naissance"},"date_naissance_jour":{"anyOf":[{"type":"integer","maximum":31.0,"minimum":1.0},{"type":"null"}],"title":"Date Naissance Jour"},"date_naissance_mois":{"anyOf":[{"type":"integer","maximum":12.0,"minimum":1.0},{"type":"null"}],"title":"Date Naissance Mois"},"date_naissance_annee":{"anyOf":[{"type":"integer","maximum":2025.0,"minimum":1900.0},{"type":"null"}],"title":"Date Naissance Annee"},"date_naissance_approximative":{"type":"boolean","title":"Date Naissance Approximative","default":false},"pere_prenoms":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Pere Prenoms"},"mere_prenoms":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Mere Prenoms"}},"type":"object","required":["nom","prenoms"],"title":"IdentiteCivileIn"},"IdentiteCivileOut":{"properties":{"enregistre":{"type":"boolean","title":"Enregistre"},"score":{"type":"integer","title":"Score"},"identite_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Identite Hash"},"doublon_potentiel":{"type":"boolean","title":"Doublon Potentiel"},"raison":{"type":"string","title":"Raison"},"doublon_user_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Doublon User Id"},"parents_requis":{"type":"boolean","title":"Parents Requis","default":false}},"type":"object","required":["enregistre","score","identite_hash","doublon_potentiel","raison"],"title":"IdentiteCivileOut"},"LangueIn":{"properties":{"langue":{"type":"string","pattern":"^(fr|en|dyu|bci|bet)$","title":"Langue"}},"type":"object","required":["langue"],"title":"LangueIn"},"MessageIn":{"properties":{"destinataire_telephone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Destinataire Telephone"},"destinataire_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Destinataire Id"},"course_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Course Id"},"contenu":{"type":"string","maxLength":2000,"minLength":1,"title":"Contenu"}},"type":"object","required":["contenu"],"title":"MessageIn"},"MultiplierOut":{"properties":{"multiplier":{"type":"number","title":"Multiplier"},"raison_alerte_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Raison Alerte Id"},"applique_at":{"type":"string","format":"date-time","title":"Applique At"},"expire_at":{"type":"string","format":"date-time","title":"Expire At"}},"type":"object","required":["multiplier","raison_alerte_id","applique_at","expire_at"],"title":"MultiplierOut"},"NoteIn":{"properties":{"note":{"type":"integer","maximum":5.0,"minimum":1.0,"title":"Note"},"commentaire":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Commentaire"}},"type":"object","required":["note"],"title":"NoteIn"},"ParrainageIn":{"properties":{"code_parrain":{"type":"string","title":"Code Parrain"}},"type":"object","required":["code_parrain"],"title":"ParrainageIn"},"PassagerPrefIn":{"properties":{"passager_id":{"type":"integer","title":"Passager Id"},"surnom":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Surnom"}},"type":"object","required":["passager_id"],"title":"PassagerPrefIn"},"PassagerPrefUpdate":{"properties":{"surnom":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Surnom"}},"type":"object","title":"PassagerPrefUpdate"},"PeageIn":{"properties":{"pays_code":{"type":"string","maxLength":2,"minLength":2,"title":"Pays Code"},"nom":{"type":"string","maxLength":120,"minLength":2,"title":"Nom"},"axe_routier":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Axe Routier"},"lat":{"anyOf":[{"type":"number","maximum":90.0,"minimum":-90.0},{"type":"null"}],"title":"Lat"},"lon":{"anyOf":[{"type":"number","maximum":180.0,"minimum":-180.0},{"type":"null"}],"title":"Lon"},"tarif_voiture_xof":{"type":"integer","title":"Tarif Voiture Xof","default":0},"tarif_moto_xof":{"type":"integer","title":"Tarif Moto Xof","default":0},"tarif_tricycle_xof":{"type":"integer","title":"Tarif Tricycle Xof","default":0},"tarif_camionnette_xof":{"type":"integer","title":"Tarif Camionnette Xof","default":0},"tarif_bus_xof":{"type":"integer","title":"Tarif Bus Xof","default":0},"tarif_camion_xof":{"type":"integer","title":"Tarif Camion Xof","default":0},"actif":{"type":"boolean","title":"Actif","default":true},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"}},"type":"object","required":["pays_code","nom"],"title":"PeageIn"},"PoolCreerIn":{"properties":{"fenetre_minutes":{"type":"integer","maximum":30.0,"minimum":1.0,"title":"Fenetre Minutes","description":"Durée d'ouverture du pool en minutes","default":5},"centre_depart_lat":{"type":"number","maximum":90.0,"minimum":-90.0,"title":"Centre Depart Lat"},"centre_depart_lon":{"type":"number","maximum":180.0,"minimum":-180.0,"title":"Centre Depart Lon"},"centre_arrivee_lat":{"type":"number","maximum":90.0,"minimum":-90.0,"title":"Centre Arrivee Lat"},"centre_arrivee_lon":{"type":"number","maximum":180.0,"minimum":-180.0,"title":"Centre Arrivee Lon"},"rayon_max_m":{"type":"integer","maximum":3000.0,"minimum":200.0,"title":"Rayon Max M","default":800},"nb_places_max":{"type":"integer","maximum":5.0,"minimum":2.0,"title":"Nb Places Max","default":3},"prix_unite_xof":{"type":"integer","maximum":20000.0,"minimum":200.0,"title":"Prix Unite Xof","description":"Prix par passager (-30% du tarif solo recommandé)"}},"type":"object","required":["centre_depart_lat","centre_depart_lon","centre_arrivee_lat","centre_arrivee_lon","prix_unite_xof"],"title":"PoolCreerIn"},"PoolRejoindreIn":{"properties":{"pool_id":{"type":"integer","title":"Pool Id"},"pickup_lat":{"type":"number","title":"Pickup Lat"},"pickup_lon":{"type":"number","title":"Pickup Lon"},"drop_lat":{"type":"number","title":"Drop Lat"},"drop_lon":{"type":"number","title":"Drop Lon"}},"type":"object","required":["pool_id","pickup_lat","pickup_lon","drop_lat","drop_lon"],"title":"PoolRejoindreIn"},"PositionIn":{"properties":{"lat":{"type":"number","maximum":90.0,"minimum":-90.0,"title":"Lat"},"lon":{"type":"number","maximum":180.0,"minimum":-180.0,"title":"Lon"}},"type":"object","required":["lat","lon"],"title":"PositionIn"},"PostIn":{"properties":{"titre":{"type":"string","maxLength":200,"minLength":3,"title":"Titre"},"contenu":{"type":"string","maxLength":10000,"minLength":10,"title":"Contenu"},"categorie":{"type":"string","title":"Categorie","default":"general"}},"type":"object","required":["titre","contenu"],"title":"PostIn"},"PourboireIn":{"properties":{"montant_xof":{"type":"integer","maximum":50000.0,"minimum":100.0,"title":"Montant Xof","description":"Montant pourboire en FCFA (100 à 50 000)"}},"type":"object","required":["montant_xof"],"title":"PourboireIn"},"ProfilChauffeurIn":{"properties":{"prenoms":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prenoms"},"nom":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nom"},"photo_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Photo Url"},"permis_numero":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Permis Numero"},"permis_categorie":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Permis Categorie"},"permis_emis_le":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Permis Emis Le"},"permis_expire_le":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Permis Expire Le"},"rccm":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rccm"},"nif":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nif"},"annee_experience":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Annee Experience"},"langues":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Langues"},"bio":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bio"}},"type":"object","title":"ProfilChauffeurIn"},"PseudoIn":{"properties":{"pseudo_public":{"anyOf":[{"type":"string","maxLength":30,"minLength":3},{"type":"null"}],"title":"Pseudo Public"},"avatar_emoji":{"anyOf":[{"type":"string","maxLength":10},{"type":"null"}],"title":"Avatar Emoji"}},"type":"object","title":"PseudoIn"},"RadarOut":{"properties":{"id":{"type":"integer","title":"Id"},"nom":{"type":"string","title":"Nom"},"axe":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Axe"},"commune":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Commune"},"type_radar":{"type":"string","title":"Type Radar"},"vitesse_max":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Vitesse Max"},"lat":{"type":"number","title":"Lat"},"lon":{"type":"number","title":"Lon"},"distance_m":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Distance M"}},"type":"object","required":["id","nom","type_radar","lat","lon"],"title":"RadarOut"},"RefusIn":{"properties":{"raison":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Raison"}},"type":"object","title":"RefusIn"},"RejeterKYCIn":{"properties":{"raison":{"type":"string","maxLength":500,"minLength":10,"title":"Raison"}},"type":"object","required":["raison"],"title":"RejeterKYCIn"},"RentrerChezMoiActiverIn":{"properties":{"destination_lat":{"type":"number","maximum":90.0,"minimum":-90.0,"title":"Destination Lat"},"destination_lon":{"type":"number","maximum":180.0,"minimum":-180.0,"title":"Destination Lon"},"label":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Label","default":"Maison"},"tolerance_km":{"type":"integer","maximum":20.0,"minimum":1.0,"title":"Tolerance Km","description":"Distance max destination_arrivee depuis ma destination","default":5}},"type":"object","required":["destination_lat","destination_lon"],"title":"RentrerChezMoiActiverIn"},"ReportIn":{"properties":{"type":{"type":"string","pattern":"^(radar_mobile|controle_police|accident|embuscade|route_bloquee|panne_route|animal_route)$","title":"Type"},"lat":{"type":"number","maximum":90.0,"minimum":-90.0,"title":"Lat"},"lon":{"type":"number","maximum":180.0,"minimum":-180.0,"title":"Lon"},"direction_deg":{"anyOf":[{"type":"number","maximum":360.0,"minimum":0.0},{"type":"null"}],"title":"Direction Deg","description":"Cap GPS du véhicule au moment du signalement (0-360)"}},"type":"object","required":["type","lat","lon"],"title":"ReportIn"},"RerouteIn":{"properties":{"lat":{"type":"number","maximum":90.0,"minimum":-90.0,"title":"Lat"},"lon":{"type":"number","maximum":180.0,"minimum":-180.0,"title":"Lon"},"adresse":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Adresse"}},"type":"object","required":["lat","lon"],"title":"RerouteIn"},"ReservationIn":{"properties":{"depart_lat":{"type":"number","maximum":90.0,"minimum":-90.0,"title":"Depart Lat"},"depart_lon":{"type":"number","maximum":180.0,"minimum":-180.0,"title":"Depart Lon"},"depart_adresse":{"type":"string","maxLength":300,"minLength":2,"title":"Depart Adresse"},"arrivee_lat":{"type":"number","maximum":90.0,"minimum":-90.0,"title":"Arrivee Lat"},"arrivee_lon":{"type":"number","maximum":180.0,"minimum":-180.0,"title":"Arrivee Lon"},"arrivee_adresse":{"type":"string","maxLength":300,"minLength":2,"title":"Arrivee Adresse"},"pour_quand":{"type":"string","format":"date-time","title":"Pour Quand","description":"ISO 8601 UTC, doit être > maintenant + 30 min"},"chauffeur_pre_assigne_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Chauffeur Pre Assigne Id","description":"ID d'un chauffeur préférentiel"},"nb_passagers":{"type":"integer","maximum":8.0,"minimum":1.0,"title":"Nb Passagers","default":1},"note_specifique":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Note Specifique"},"type_demande":{"type":"string","pattern":"^(standard|inter_ville|colis)$","title":"Type Demande","default":"standard"}},"type":"object","required":["depart_lat","depart_lon","depart_adresse","arrivee_lat","arrivee_lon","arrivee_adresse","pour_quand"],"title":"ReservationIn"},"RetraitIn":{"properties":{"montant_xof":{"type":"integer","maximum":2000000.0,"minimum":500.0,"title":"Montant Xof"},"moyen":{"type":"string","title":"Moyen","default":"wave"},"telephone_dest":{"type":"string","title":"Telephone Dest"}},"type":"object","required":["montant_xof","telephone_dest"],"title":"RetraitIn"},"SatisfactionIn":{"properties":{"note":{"type":"integer","maximum":5.0,"minimum":1.0,"title":"Note"}},"type":"object","required":["note"],"title":"SatisfactionIn"},"SignalementIn":{"properties":{"target_user_id":{"type":"integer","title":"Target User Id"},"categorie":{"type":"string","pattern":"^(harcelement|vol|conduite_dangereuse|comportement_inapproprie|agression_physique|agression_verbale|fraude|vehicule_non_conforme|no_show|autre)$","title":"Categorie"},"description":{"type":"string","maxLength":2000,"minLength":10,"title":"Description"},"course_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Course Id"},"photo_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Photo Url"},"gravite":{"anyOf":[{"type":"integer","maximum":5.0,"minimum":1.0},{"type":"null"}],"title":"Gravite","description":"Override default. Sinon dérivé de la catégorie."}},"type":"object","required":["target_user_id","categorie","description"],"title":"SignalementIn"},"SosContactIn":{"properties":{"nom":{"type":"string","title":"Nom"},"telephone":{"type":"string","title":"Telephone"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"relation":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Relation"},"priorite":{"type":"integer","title":"Priorite","default":1}},"type":"object","required":["nom","telephone"],"title":"SosContactIn"},"SosDeclencherIn":{"properties":{"lat":{"type":"number","title":"Lat"},"lon":{"type":"number","title":"Lon"},"motif":{"type":"string","title":"Motif","default":"agression"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"course_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Course Id"}},"type":"object","required":["lat","lon"],"title":"SosDeclencherIn"},"TarifIn":{"properties":{"tarif_base_xof":{"anyOf":[{"type":"integer","maximum":10000.0,"minimum":0.0},{"type":"null"}],"title":"Tarif Base Xof"},"tarif_km_xof":{"anyOf":[{"type":"integer","maximum":2000.0,"minimum":50.0},{"type":"null"}],"title":"Tarif Km Xof"},"tarif_minute_xof":{"anyOf":[{"type":"integer","maximum":200.0,"minimum":0.0},{"type":"null"}],"title":"Tarif Minute Xof"}},"type":"object","title":"TarifIn"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"ValiderKYCIn":{"properties":{"note_admin":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Note Admin"}},"type":"object","title":"ValiderKYCIn"},"VehiculeIn":{"properties":{"immatriculation":{"type":"string","title":"Immatriculation"},"marque":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Marque"},"modele":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Modele"},"annee":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Annee"},"couleur":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Couleur"},"type_vehicule":{"type":"string","title":"Type Vehicule","default":"berline"},"nb_places":{"type":"integer","title":"Nb Places","default":4},"climatisation":{"type":"boolean","title":"Climatisation","default":false},"photo_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Photo Url"}},"type":"object","required":["immatriculation"],"title":"VehiculeIn"},"VoteIn":{"properties":{"action":{"type":"string","pattern":"^(confirm|deny)$","title":"Action"}},"type":"object","required":["action"],"title":"VoteIn"},"ZoneIn":{"properties":{"ville_id":{"type":"integer","title":"Ville Id"},"principale":{"type":"boolean","title":"Principale","default":false}},"type":"object","required":["ville_id"],"title":"ZoneIn"}}},"tags":[{"name":"auth","description":"Authentification OTP SMS + JWT + identité civile"},{"name":"courses","description":"Création, démarrage, fin, annulation, notation des courses"},{"name":"demandes","description":"Demandes de course / livraison + dispatch ring"},{"name":"chauffeurs","description":"Profil, KYC, véhicule, position, tarifs personnalisés"},{"name":"tarifs","description":"Barème personnel chauffeur + référence marché Abidjan"},{"name":"notations","description":"Système de notation bidirectionnel passager↔chauffeur"},{"name":"reports","description":"Signalements crowdsourcés (radars, contrôles, accidents)"},{"name":"fcm","description":"Push notifications via Firebase Cloud Messaging"},{"name":"support","description":"Support client IA-first (Claude Haiku) + escalade"},{"name":"paiements","description":"PayTech / PawaPay / FedaPay (mobile money UEMOA)"},{"name":"admin","description":"Endpoints administrateur (auth X-Admin-Password)"}]}