{"openapi":"3.0.3","info":{"title":"API Localités du Sénégal","version":"1.0.0","description":"## API de gestion des localités administratives du Sénégal\n\nCette API ultra-performante permet de gérer et consulter l'ensemble des localités\ndu Sénégal organisées en 5 niveaux hiérarchiques :\n\n1. **Région** — 14 régions administratives\n2. **Département** — Subdivisions des régions\n3. **Commune/Arrondissement/Ville** — Unités administratives intermédiaires\n4. **Commune** — Collectivités locales\n5. **Quartier/Village/Hameau** — Unités de base\n\n### Authentification\nToutes les requêtes nécessitent une clé API valide transmise via :\n- En-tête `X-API-Key: sngl_live_<votre_cle>`\n- En-tête `Authorization: Bearer sngl_live_<votre_cle>`\n\n### Limites de débit\n- **Lecture** : 1000 requêtes/minute par clé API\n- **Écriture** : 100 requêtes/minute par clé API\n- **Sans clé** : 100 requêtes/minute par IP","contact":{"name":"Support API","email":"api@senegal-localites.sn"},"license":{"name":"MIT"}},"servers":[{"url":"https://api.senegal-localites.sn","description":"Production"},{"url":"http://localhost:3000","description":"Développement local"}],"tags":[{"name":"Localités","description":"Gestion complète des localités (vue hiérarchique aplatie)"},{"name":"Régions","description":"Gestion des 14 régions administratives"},{"name":"Départements","description":"Gestion des départements"},{"name":"Communes-Arrondissements-Villes","description":"Gestion des communes, arrondissements et villes"},{"name":"Communes","description":"Gestion des communes (collectivités locales)"},{"name":"Quartiers","description":"Gestion des quartiers, villages et hameaux"},{"name":"Recherche","description":"Recherche textuelle et full-text"},{"name":"Santé","description":"Statut et métriques de l'API"}],"components":{"securitySchemes":{"ApiKeyHeader":{"type":"apiKey","in":"header","name":"X-API-Key","description":"Clé API au format `sngl_live_<64 caractères hex>`"},"BearerAuth":{"type":"http","scheme":"bearer","description":"Clé API transmise comme Bearer token"}},"schemas":{"LocaliteComplete":{"type":"object","required":["id","region","departement","com_arrt_ville","commune","quartier_village_hameau"],"properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"},"region":{"type":"string","example":"DAKAR"},"departement":{"type":"string","example":"DAKAR"},"com_arrt_ville":{"type":"string","example":"DAKAR"},"commune":{"type":"string","example":"PLATEAU"},"quartier_village_hameau":{"type":"string","example":"CENTRE-VILLE"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"ErreurApi":{"type":"object","required":["statut","code","message","timestamp"],"properties":{"statut":{"type":"integer","example":400},"code":{"type":"string","example":"PARAMETRES_INVALIDES"},"message":{"type":"string","example":"Les paramètres fournis sont invalides."},"details":{"type":"object","nullable":true},"timestamp":{"type":"string","format":"date-time"},"chemin":{"type":"string","example":"/api/localites"}}},"PaginationMeta":{"type":"object","properties":{"total":{"type":"integer","example":1250},"limite":{"type":"integer","example":20},"curseur_suivant":{"type":"string","nullable":true},"a_suivant":{"type":"boolean"}}},"CreerLocalite":{"type":"object","required":["region","departement","com_arrt_ville","commune","quartier_village_hameau"],"properties":{"region":{"type":"string","minLength":2,"maxLength":100,"example":"DAKAR"},"departement":{"type":"string","minLength":2,"maxLength":100,"example":"DAKAR"},"com_arrt_ville":{"type":"string","minLength":2,"maxLength":150,"example":"DAKAR"},"commune":{"type":"string","minLength":2,"maxLength":150,"example":"PLATEAU"},"quartier_village_hameau":{"type":"string","minLength":2,"maxLength":200,"example":"CENTRE-VILLE"},"code_quartier":{"type":"string","maxLength":10,"nullable":true,"example":"QV_001"}}}},"responses":{"NonAuthentifie":{"description":"Clé API manquante ou invalide","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErreurApi"}}}},"TropDeRequetes":{"description":"Limite de débit atteinte","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}},"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErreurApi"}}}},"ErreurInterne":{"description":"Erreur interne du serveur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErreurApi"}}}}}},"security":[{"ApiKeyHeader":[]}],"paths":{"/api/localites":{"get":{"tags":["Localités"],"summary":"Lister les localités avec filtrage granulaire","description":"Retourne une liste paginée de localités avec filtrage multi-niveaux. Résultat mis en cache Redis (TTL: 5 min).","operationId":"listerLocalites","parameters":[{"name":"region","in":"query","schema":{"type":"string"},"description":"Filtrer par région (insensible à la casse)","example":"Dakar"},{"name":"departement","in":"query","schema":{"type":"string"},"description":"Filtrer par département"},{"name":"com_arrt_ville","in":"query","schema":{"type":"string"},"description":"Filtrer par commune/arrondissement/ville"},{"name":"commune","in":"query","schema":{"type":"string"},"description":"Filtrer par commune"},{"name":"quartier","in":"query","schema":{"type":"string"},"description":"Filtrer par quartier/village/hameau"},{"name":"limite","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"description":"Nombre de résultats par page"},{"name":"curseur","in":"query","schema":{"type":"string"},"description":"Curseur de pagination (opaque)"},{"name":"inclure_hierarchie","in":"query","schema":{"type":"boolean","default":false},"description":"Inclure les données hiérarchiques complètes"}],"responses":{"200":{"description":"Liste des localités","headers":{"X-Cache":{"schema":{"type":"string","enum":["HIT","MISS"]}},"X-Response-Time":{"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"statut":{"type":"integer","example":200},"donnees":{"type":"array","items":{"$ref":"#/components/schemas/LocaliteComplete"}},"meta":{"$ref":"#/components/schemas/PaginationMeta"},"timestamp":{"type":"string","format":"date-time"}}}}}},"400":{"description":"Paramètres invalides","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErreurApi"}}}},"401":{"$ref":"#/components/responses/NonAuthentifie"},"429":{"$ref":"#/components/responses/TropDeRequetes"},"500":{"$ref":"#/components/responses/ErreurInterne"}}},"post":{"tags":["Localités"],"summary":"Créer une nouvelle localité","description":"Crée une nouvelle localité en créant automatiquement les niveaux hiérarchiques manquants.","operationId":"creerLocalite","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreerLocalite"}}}},"responses":{"201":{"description":"Localité créée avec succès"},"400":{"description":"Corps de requête invalide"},"401":{"$ref":"#/components/responses/NonAuthentifie"},"409":{"description":"La localité existe déjà"},"429":{"$ref":"#/components/responses/TropDeRequetes"},"500":{"$ref":"#/components/responses/ErreurInterne"}}}},"/api/localites/{id}":{"get":{"tags":["Localités"],"summary":"Obtenir une localité par ID","operationId":"obtenirLocalite","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Localité trouvée"},"401":{"$ref":"#/components/responses/NonAuthentifie"},"404":{"description":"Localité introuvable"},"500":{"$ref":"#/components/responses/ErreurInterne"}}},"put":{"tags":["Localités"],"summary":"Mettre à jour une localité","operationId":"mettreAJourLocalite","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreerLocalite"}}}},"responses":{"200":{"description":"Localité mise à jour"},"400":{"description":"Corps de requête invalide"},"401":{"$ref":"#/components/responses/NonAuthentifie"},"404":{"description":"Localité introuvable"},"429":{"$ref":"#/components/responses/TropDeRequetes"},"500":{"$ref":"#/components/responses/ErreurInterne"}}},"delete":{"tags":["Localités"],"summary":"Supprimer une localité","operationId":"supprimerLocalite","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Localité supprimée"},"401":{"$ref":"#/components/responses/NonAuthentifie"},"404":{"description":"Localité introuvable"},"500":{"$ref":"#/components/responses/ErreurInterne"}}}},"/api/regions":{"get":{"tags":["Régions"],"summary":"Lister les régions","operationId":"listerRegions","parameters":[{"name":"nom","in":"query","schema":{"type":"string"},"description":"Filtrer par nom"},{"name":"limite","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"curseur","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Liste des régions"},"401":{"$ref":"#/components/responses/NonAuthentifie"},"500":{"$ref":"#/components/responses/ErreurInterne"}}},"post":{"tags":["Régions"],"summary":"Créer une région","operationId":"creerRegion","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["nom"],"properties":{"nom":{"type":"string","example":"DAKAR"},"code":{"type":"string","example":"REG_DAK"}}}}}},"responses":{"201":{"description":"Région créée"},"400":{"description":"Corps invalide"},"401":{"$ref":"#/components/responses/NonAuthentifie"},"409":{"description":"Région existante"},"500":{"$ref":"#/components/responses/ErreurInterne"}}}},"/api/regions/{id}":{"get":{"tags":["Régions"],"summary":"Obtenir une région par ID (avec ses départements)","operationId":"obtenirRegion","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Région trouvée"},"401":{"$ref":"#/components/responses/NonAuthentifie"},"404":{"description":"Région introuvable"},"500":{"$ref":"#/components/responses/ErreurInterne"}}},"put":{"tags":["Régions"],"summary":"Mettre à jour une région","operationId":"mettreAJourRegion","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"nom":{"type":"string"},"code":{"type":"string"}}}}}},"responses":{"200":{"description":"Région mise à jour"},"401":{"$ref":"#/components/responses/NonAuthentifie"},"404":{"description":"Région introuvable"},"500":{"$ref":"#/components/responses/ErreurInterne"}}},"delete":{"tags":["Régions"],"summary":"Supprimer une région","operationId":"supprimerRegion","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Région supprimée"},"401":{"$ref":"#/components/responses/NonAuthentifie"},"404":{"description":"Région introuvable"},"500":{"$ref":"#/components/responses/ErreurInterne"}}}},"/api/departements":{"get":{"tags":["Départements"],"summary":"Lister les départements","operationId":"listerDepartements","parameters":[{"name":"nom","in":"query","schema":{"type":"string"}},{"name":"region_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Filtrer par région"},{"name":"limite","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"curseur","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Liste des départements"},"401":{"$ref":"#/components/responses/NonAuthentifie"},"500":{"$ref":"#/components/responses/ErreurInterne"}}},"post":{"tags":["Départements"],"summary":"Créer un département","operationId":"creerDepartement","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["nom","region_id"],"properties":{"nom":{"type":"string","example":"DAKAR"},"region_id":{"type":"string","format":"uuid"},"code":{"type":"string"}}}}}},"responses":{"201":{"description":"Département créé"},"401":{"$ref":"#/components/responses/NonAuthentifie"},"404":{"description":"Région introuvable"},"409":{"description":"Département existant"},"500":{"$ref":"#/components/responses/ErreurInterne"}}}},"/api/departements/{id}":{"get":{"tags":["Départements"],"summary":"Obtenir un département par ID (avec ses communes/arrondissements)","operationId":"obtenirDepartement","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Département trouvé"},"401":{"$ref":"#/components/responses/NonAuthentifie"},"404":{"description":"Département introuvable"},"500":{"$ref":"#/components/responses/ErreurInterne"}}},"put":{"tags":["Départements"],"summary":"Mettre à jour un département","operationId":"mettreAJourDepartement","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"nom":{"type":"string"},"region_id":{"type":"string","format":"uuid"},"code":{"type":"string"}}}}}},"responses":{"200":{"description":"Département mis à jour"},"401":{"$ref":"#/components/responses/NonAuthentifie"},"404":{"description":"Département introuvable"},"500":{"$ref":"#/components/responses/ErreurInterne"}}},"delete":{"tags":["Départements"],"summary":"Supprimer un département","operationId":"supprimerDepartement","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Département supprimé"},"401":{"$ref":"#/components/responses/NonAuthentifie"},"404":{"description":"Département introuvable"},"500":{"$ref":"#/components/responses/ErreurInterne"}}}},"/api/com-arrt-villes":{"get":{"tags":["Communes-Arrondissements-Villes"],"summary":"Lister les communes/arrondissements/villes","operationId":"listerComArrtVilles","parameters":[{"name":"nom","in":"query","schema":{"type":"string"}},{"name":"departement_id","in":"query","schema":{"type":"string","format":"uuid"}},{"name":"limite","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"curseur","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Liste des communes/arrondissements/villes"},"401":{"$ref":"#/components/responses/NonAuthentifie"},"500":{"$ref":"#/components/responses/ErreurInterne"}}},"post":{"tags":["Communes-Arrondissements-Villes"],"summary":"Créer une commune/arrondissement/ville","operationId":"creerComArrtVille","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["nom","departement_id"],"properties":{"nom":{"type":"string"},"departement_id":{"type":"string","format":"uuid"},"code":{"type":"string"}}}}}},"responses":{"201":{"description":"Créé avec succès"},"401":{"$ref":"#/components/responses/NonAuthentifie"},"404":{"description":"Département introuvable"},"409":{"description":"Déjà existant"},"500":{"$ref":"#/components/responses/ErreurInterne"}}}},"/api/com-arrt-villes/{id}":{"get":{"tags":["Communes-Arrondissements-Villes"],"summary":"Obtenir par ID (avec ses communes)","operationId":"obtenirComArrtVille","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Trouvé"},"401":{"$ref":"#/components/responses/NonAuthentifie"},"404":{"description":"Introuvable"},"500":{"$ref":"#/components/responses/ErreurInterne"}}},"put":{"tags":["Communes-Arrondissements-Villes"],"summary":"Mettre à jour","operationId":"mettreAJourComArrtVille","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"nom":{"type":"string"},"departement_id":{"type":"string","format":"uuid"},"code":{"type":"string"}}}}}},"responses":{"200":{"description":"Mis à jour"},"401":{"$ref":"#/components/responses/NonAuthentifie"},"404":{"description":"Introuvable"},"500":{"$ref":"#/components/responses/ErreurInterne"}}},"delete":{"tags":["Communes-Arrondissements-Villes"],"summary":"Supprimer","operationId":"supprimerComArrtVille","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Supprimé"},"401":{"$ref":"#/components/responses/NonAuthentifie"},"404":{"description":"Introuvable"},"500":{"$ref":"#/components/responses/ErreurInterne"}}}},"/api/communes":{"get":{"tags":["Communes"],"summary":"Lister les communes","operationId":"listerCommunes","parameters":[{"name":"nom","in":"query","schema":{"type":"string"}},{"name":"com_arrt_ville_id","in":"query","schema":{"type":"string","format":"uuid"}},{"name":"limite","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"curseur","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Liste des communes"},"401":{"$ref":"#/components/responses/NonAuthentifie"},"500":{"$ref":"#/components/responses/ErreurInterne"}}},"post":{"tags":["Communes"],"summary":"Créer une commune","operationId":"creerCommune","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["nom","com_arrt_ville_id"],"properties":{"nom":{"type":"string"},"com_arrt_ville_id":{"type":"string","format":"uuid"},"code":{"type":"string"}}}}}},"responses":{"201":{"description":"Commune créée"},"401":{"$ref":"#/components/responses/NonAuthentifie"},"404":{"description":"Commune/Arrondissement/Ville introuvable"},"409":{"description":"Commune existante"},"500":{"$ref":"#/components/responses/ErreurInterne"}}}},"/api/communes/{id}":{"get":{"tags":["Communes"],"summary":"Obtenir une commune par ID (avec ses quartiers)","operationId":"obtenirCommune","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Commune trouvée"},"401":{"$ref":"#/components/responses/NonAuthentifie"},"404":{"description":"Commune introuvable"},"500":{"$ref":"#/components/responses/ErreurInterne"}}},"put":{"tags":["Communes"],"summary":"Mettre à jour une commune","operationId":"mettreAJourCommune","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"nom":{"type":"string"},"com_arrt_ville_id":{"type":"string","format":"uuid"},"code":{"type":"string"}}}}}},"responses":{"200":{"description":"Commune mise à jour"},"401":{"$ref":"#/components/responses/NonAuthentifie"},"404":{"description":"Commune introuvable"},"500":{"$ref":"#/components/responses/ErreurInterne"}}},"delete":{"tags":["Communes"],"summary":"Supprimer une commune","operationId":"supprimerCommune","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Commune supprimée"},"401":{"$ref":"#/components/responses/NonAuthentifie"},"404":{"description":"Commune introuvable"},"500":{"$ref":"#/components/responses/ErreurInterne"}}}},"/api/quartiers":{"get":{"tags":["Quartiers"],"summary":"Lister les quartiers/villages/hameaux","operationId":"listerQuartiers","parameters":[{"name":"nom","in":"query","schema":{"type":"string"}},{"name":"commune_id","in":"query","schema":{"type":"string","format":"uuid"}},{"name":"limite","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"curseur","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Liste des quartiers/villages/hameaux"},"401":{"$ref":"#/components/responses/NonAuthentifie"},"500":{"$ref":"#/components/responses/ErreurInterne"}}},"post":{"tags":["Quartiers"],"summary":"Créer un quartier/village/hameau","operationId":"creerQuartier","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["nom","commune_id"],"properties":{"nom":{"type":"string"},"commune_id":{"type":"string","format":"uuid"},"code":{"type":"string"}}}}}},"responses":{"201":{"description":"Créé avec succès"},"401":{"$ref":"#/components/responses/NonAuthentifie"},"404":{"description":"Commune introuvable"},"409":{"description":"Déjà existant"},"500":{"$ref":"#/components/responses/ErreurInterne"}}}},"/api/quartiers/{id}":{"get":{"tags":["Quartiers"],"summary":"Obtenir un quartier/village/hameau par ID","operationId":"obtenirQuartier","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Trouvé"},"401":{"$ref":"#/components/responses/NonAuthentifie"},"404":{"description":"Introuvable"},"500":{"$ref":"#/components/responses/ErreurInterne"}}},"put":{"tags":["Quartiers"],"summary":"Mettre à jour un quartier/village/hameau","operationId":"mettreAJourQuartier","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"nom":{"type":"string"},"commune_id":{"type":"string","format":"uuid"},"code":{"type":"string"}}}}}},"responses":{"200":{"description":"Mis à jour"},"401":{"$ref":"#/components/responses/NonAuthentifie"},"404":{"description":"Introuvable"},"500":{"$ref":"#/components/responses/ErreurInterne"}}},"delete":{"tags":["Quartiers"],"summary":"Supprimer un quartier/village/hameau","operationId":"supprimerQuartier","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Supprimé"},"401":{"$ref":"#/components/responses/NonAuthentifie"},"404":{"description":"Introuvable"},"500":{"$ref":"#/components/responses/ErreurInterne"}}}},"/api/localites/search":{"get":{"tags":["Recherche"],"summary":"Recherche textuelle full-text","description":"Recherche dans tous les niveaux de localités via PostgreSQL Full-Text Search (tsvector/tsquery). Supporte la recherche floue.","operationId":"rechercherLocalites","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":2},"description":"Terme de recherche","example":"Plateau"},{"name":"limite","in":"query","schema":{"type":"integer","minimum":1,"maximum":50,"default":10}},{"name":"niveau","in":"query","schema":{"type":"string","enum":["region","departement","com_arrt_ville","commune","quartier","tous"],"default":"tous"},"description":"Niveau hiérarchique de recherche"}],"responses":{"200":{"description":"Résultats de recherche"},"400":{"description":"Paramètre 'q' manquant ou invalide"},"401":{"$ref":"#/components/responses/NonAuthentifie"},"429":{"$ref":"#/components/responses/TropDeRequetes"},"500":{"$ref":"#/components/responses/ErreurInterne"}}}}}}