# API NOVIRA · description OpenAPI 3.1 # Exemples tirés du jeu de démonstration contracts/demo (situation au 15/09/2026). openapi: '3.1.0' info: title: API NOVIRA version: '0.1.0' summary: API métier de la plateforme de distribution B2B NOVIRA. description: |- NOVIRA est la plateforme de distribution B2B de CYBASTION pour la connectivité Internet par satellite Starlink. Elle réunit le référencement des partenaires distributeurs, la gestion des clients et de leurs sites, les réservations, le catalogue, puis le cycle de vente jusqu'à la commission. Cette API est le seul point d'écriture de la plateforme : le back-office CYBASTION et l'application mobile Flutter l'appellent pour toute opération métier. ## Authentification Chaque appel, sauf `/api/v1/sante`, porte le jeton d'accès délivré par Supabase Auth après connexion par e-mail : `Authorization: Bearer `. Les droits sont vérifiés par permission, jamais par nom de rôle. Un utilisateur peut cumuler plusieurs rôles ; ses permissions sont l'union de celles de ses rôles (`GET /api/v1/moi`). Les données sont cloisonnées par organisation. ## Pagination Les listes acceptent `page` (à partir de 1) et `taille` (de 1 à 100, 20 par défaut) et renvoient `{ donnees, pagination }`. ## Erreurs Toute erreur renvoie `{ code, message, details }` : un code stable pour le programme, un message en français prêt à afficher et des détails facultatifs. ## Conventions - Identifiants UUID ; noms de champs identiques au modèle de données. - Montants en francs CFA (XOF), hors taxes sauf mention contraire. - Dates au format `AAAA-MM-JJ`, horodatages ISO 8601 en UTC (heure d'Abidjan). contact: name: Équipe NOVIRA · CYBASTION license: name: Propriétaire · usage réservé à CYBASTION identifier: LicenseRef-CYBASTION-Proprietaire servers: - url: 'https://api-novira.optima.aora.tech' description: Environnement en ligne tags: - name: Santé description: Disponibilité du service. - name: Session description: 'Utilisateur connecté, organisation, rôles et permissions.' - name: Partenaires description: 'Partenaires distributeurs, zones couvertes et contrat-cadre.' - name: Conformité description: Pièces KYC et vérification documentaire. - name: Clients description: 'Entreprises clientes, contacts et sites.' - name: Réservations description: Demandes de réservation des partenaires et contrôle de doublon. - name: Catalogue description: Forfaits data et tarifs datés. security: - jetonAcces: [] paths: '/api/v1/sante': get: tags: - Santé operationId: lireSante summary: Vérifier la disponibilité du service security: [] description: 'Point de contrôle sans authentification, utilisé par la supervision et par les applications avant la connexion.' responses: '200': description: Service disponible. content: 'application/json': schema: '$ref': '#/components/schemas/Sante' example: statut: ok version: '0.1.0' horodatage: '2026-09-15T14:00:00Z' '429': description: Trop d'appels sur une courte période. content: 'application/json': schema: '$ref': '#/components/schemas/Erreur' example: code: trop_de_requetes message: Trop de requêtes. Merci de patienter quelques instants avant de réessayer. details: reessayer_dans_secondes: 30 '503': description: Service indisponible. content: 'application/json': schema: '$ref': '#/components/schemas/Erreur' example: code: service_indisponible message: Le service est momentanément indisponible. Merci de réessayer dans quelques instants. details: null '/api/v1/moi': get: tags: - Session operationId: lireMoi summary: Lire la session de l'utilisateur connecté description: "Renvoie l'utilisateur, son organisation, tous ses rôles et l'union de leurs permissions. C'est la seule source des droits côté interface." responses: '200': description: 'Session courante. Exemple : un contrôleur qui cumule les rôles Finance et Opérations.' content: 'application/json': schema: '$ref': '#/components/schemas/Moi' example: utilisateur: id: '21000000-0000-4000-8000-000000000007' organisation_id: '20000000-0000-4000-8000-000000000001' role_id: '10000000-0000-4000-8000-000000000004' prenom: Ibrahim nom: Ouattara email: 'ibrahim.ouattara@demo.novira.ci' telephone: '+225 07 49 20 63 18' fonction: Contrôleur de gestion et opérations actif: true double_authentification: true derniere_connexion: '2026-09-15T09:12:00Z' organisation: id: '20000000-0000-4000-8000-000000000001' type: cybastion nom: CYBASTION statut: active cree_le: '2026-01-05T08:00:00Z' modifie_le: '2026-01-05T08:00:00Z' roles: - code: cybastion_finance libelle: Finance type_organisation: cybastion principal: true - code: cybastion_operations libelle: Opérations type_organisation: cybastion principal: false permissions: - clients.consulter - clients.credit_approuver - eligibilite.verifier - paiements.valider - factures.emettre - remboursements.gerer - commissions.consulter - commissions.verser - installations.gerer - pv.charger - activations.gerer - evenements.gerer - tickets.traiter - actions.gerer - reporting.consulter - backoffice.acceder - tableau_de_bord.consulter - catalogue.consulter '401': '$ref': '#/components/responses/NonAuthentifie' '/api/v1/partenaires': get: tags: - Partenaires operationId: listerPartenaires summary: Lister les partenaires description: 'Permission requise : `partenaires.consulter`. Tri par raison sociale.' parameters: - '$ref': '#/components/parameters/Page' - '$ref': '#/components/parameters/Taille' - '$ref': '#/components/parameters/Recherche' - name: statut in: query required: false description: Filtre sur le statut de référencement. schema: '$ref': '#/components/schemas/StatutPartenaire' - name: zone_id in: query required: false description: Partenaires couvrant cette zone. schema: type: string format: uuid responses: '200': description: Page de partenaires. content: 'application/json': schema: '$ref': '#/components/schemas/PagePartenaires' example: donnees: - id: '30000000-0000-4000-8000-000000000001' organisation_id: '20000000-0000-4000-8000-000000000003' raison_sociale: Akwaba Connect Services forme_juridique: SARL rccm: CI-ABJ-2017-B-21458 ncc: '1721458C' adresse: 'Riviera Palmeraie, rue I 45, Cocody' ville: Abidjan zone_principale_id: '50000000-0000-4000-8000-000000000023' telephone: '+225 27 22 49 18 30' email: 'akwaba-connect@demo.novira.ci' capacite_commerciale: 8 mode_versement: virement rib: CI008 01101 012345678901 27 numero_mobile_money: null logo_fichier_id: null presentation: "Intégrateur réseau installé à Cocody, Akwaba Connect Services équipe cliniques, écoles et PME d'Abidjan en connectivité satellite, de l'étude de site à la mise en service." profil_publie: true statut: actif valide_par: '21000000-0000-4000-8000-000000000002' valide_le: '2026-03-18T10:30:00Z' cree_le: '2026-02-24T09:30:00Z' modifie_le: '2026-09-02T09:05:00Z' - id: '30000000-0000-4000-8000-000000000002' organisation_id: '20000000-0000-4000-8000-000000000004' raison_sociale: Lagune Réseaux forme_juridique: SA rccm: CI-ABJ-2015-B-09832 ncc: '1509832H' adresse: 'Boulevard de Marseille, immeuble Les Cocotiers, Marcory' ville: Abidjan zone_principale_id: '50000000-0000-4000-8000-000000000026' telephone: '+225 27 21 26 47 90' email: 'lagune-reseaux@demo.novira.ci' capacite_commerciale: 12 mode_versement: virement rib: CI034 01001 004512876301 58 numero_mobile_money: null logo_fichier_id: null presentation: "Spécialiste des réseaux d'entreprise depuis 2015, Lagune Réseaux accompagne banques, hôtels et acteurs portuaires du sud du pays avec une équipe grands comptes dédiée." profil_publie: true statut: actif valide_par: '21000000-0000-4000-8000-000000000002' valide_le: '2026-04-07T11:00:00Z' cree_le: '2026-03-09T10:15:00Z' modifie_le: '2026-09-11T10:12:00Z' pagination: page: 1 taille: 2 total: 5 pages: 3 '401': '$ref': '#/components/responses/NonAuthentifie' '403': '$ref': '#/components/responses/AccesRefuse' '422': '$ref': '#/components/responses/ParametresInvalides' '/api/v1/partenaires/{id}': get: tags: - Partenaires operationId: lirePartenaire summary: Lire la fiche d'un partenaire description: 'Permission requise : `partenaires.consulter`. Inclut les zones couvertes, les secteurs ciblés et le contrat-cadre en vigueur.' parameters: - '$ref': '#/components/parameters/IdPartenaire' responses: '200': description: Fiche du partenaire. content: 'application/json': schema: '$ref': '#/components/schemas/PartenaireDetail' example: id: '30000000-0000-4000-8000-000000000001' organisation_id: '20000000-0000-4000-8000-000000000003' raison_sociale: Akwaba Connect Services forme_juridique: SARL rccm: CI-ABJ-2017-B-21458 ncc: '1721458C' adresse: 'Riviera Palmeraie, rue I 45, Cocody' ville: Abidjan zone_principale_id: '50000000-0000-4000-8000-000000000023' telephone: '+225 27 22 49 18 30' email: 'akwaba-connect@demo.novira.ci' capacite_commerciale: 8 mode_versement: virement rib: CI008 01101 012345678901 27 numero_mobile_money: null logo_fichier_id: null presentation: "Intégrateur réseau installé à Cocody, Akwaba Connect Services équipe cliniques, écoles et PME d'Abidjan en connectivité satellite, de l'étude de site à la mise en service." profil_publie: true statut: actif valide_par: '21000000-0000-4000-8000-000000000002' valide_le: '2026-03-18T10:30:00Z' cree_le: '2026-02-24T09:30:00Z' modifie_le: '2026-09-02T09:05:00Z' zones: - id: '50000000-0000-4000-8000-000000000023' code: CI-ABJ-COCODY libelle: Cocody type: commune parent_id: '50000000-0000-4000-8000-000000000012' - id: '50000000-0000-4000-8000-000000000024' code: CI-ABJ-PLATEAU libelle: Plateau type: commune parent_id: '50000000-0000-4000-8000-000000000012' - id: '50000000-0000-4000-8000-000000000025' code: CI-ABJ-YOPOUGON libelle: Yopougon type: commune parent_id: '50000000-0000-4000-8000-000000000012' secteurs: - id: '51000000-0000-4000-8000-000000000004' code: sante libelle: Santé - id: '51000000-0000-4000-8000-000000000005' code: education libelle: Éducation - id: '51000000-0000-4000-8000-000000000015' code: services_professionnels libelle: Services professionnels - id: '51000000-0000-4000-8000-000000000006' code: hotellerie_restauration libelle: Hôtellerie / restauration contrat_cadre: id: '32000000-0000-4000-8000-000000000001' numero: CCA-2026-000001 partenaire_id: '30000000-0000-4000-8000-000000000001' conditions_id: '31000000-0000-4000-8000-000000000001' fichier_genere_id: '53000000-0000-4000-8000-000000000001' fichier_signe_id: '53000000-0000-4000-8000-000000000002' statut: signe date_debut: '2026-03-18' date_fin: '2027-03-17' signe_le: '2026-03-17T11:00:00Z' cree_le: '2026-03-10T15:20:00Z' modifie_le: '2026-03-17T11:00:00Z' '401': '$ref': '#/components/responses/NonAuthentifie' '403': '$ref': '#/components/responses/AccesRefuse' '404': '$ref': '#/components/responses/Introuvable' '/api/v1/partenaires/{id}/documents-kyc': get: tags: - Conformité operationId: listerDocumentsKycPartenaire summary: Lister les pièces KYC d'un partenaire description: 'Permission requise : `partenaires.consulter`. Une pièce obligatoire absente de la liste est à signaler comme manquante. Le téléchargement passe par un lien signé à durée courte.' parameters: - '$ref': '#/components/parameters/IdPartenaire' - name: statut in: query required: false description: Filtre sur le statut de la pièce. schema: '$ref': '#/components/schemas/StatutDocument' responses: '200': description: 'Pièces du partenaire. Exemple : un dossier à compléter.' content: 'application/json': schema: '$ref': '#/components/schemas/ListeDocumentsKyc' example: donnees: - id: '54000000-0000-4000-8000-000000000022' organisation_id: '20000000-0000-4000-8000-000000000007' type_document_id: '52000000-0000-4000-8000-000000000001' fichier_id: '53000000-0000-4000-8000-000000000028' date_emission: '2021-09-27' date_expiration: null statut: valide motif: null verifie_par: '21000000-0000-4000-8000-000000000003' verifie_le: '2026-08-25T11:00:00Z' cree_le: '2026-08-20T09:30:00Z' modifie_le: '2026-08-25T11:00:00Z' type_document: id: '52000000-0000-4000-8000-000000000001' code: partenaire_rccm libelle: Registre du commerce (RCCM) cible: partenaire obligatoire: true validite_mois: null actif: true fichier: id: '53000000-0000-4000-8000-000000000028' nom_original: RCCM_Émeraude_Systèmes.pdf type_mime: application/pdf taille_octets: 2163339 statut_scan: sain - id: '54000000-0000-4000-8000-000000000023' organisation_id: '20000000-0000-4000-8000-000000000007' type_document_id: '52000000-0000-4000-8000-000000000002' fichier_id: '53000000-0000-4000-8000-000000000029' date_emission: '2026-04-15' date_expiration: '2026-10-14' statut: rejete motif: 'Attestation établie il y a plus de trois mois : merci de déposer une attestation de moins de trois mois.' verifie_par: '21000000-0000-4000-8000-000000000003' verifie_le: '2026-08-25T11:10:00Z' cree_le: '2026-08-20T09:35:00Z' modifie_le: '2026-08-25T11:10:00Z' type_document: id: '52000000-0000-4000-8000-000000000002' code: partenaire_attestation_fiscale libelle: Attestation de régularité fiscale cible: partenaire obligatoire: true validite_mois: null actif: true fichier: id: '53000000-0000-4000-8000-000000000029' nom_original: Attestation_fiscale_Émeraude_Systèmes.pdf type_mime: application/pdf taille_octets: 2236796 statut_scan: sain - id: '54000000-0000-4000-8000-000000000024' organisation_id: '20000000-0000-4000-8000-000000000007' type_document_id: '52000000-0000-4000-8000-000000000003' fichier_id: '53000000-0000-4000-8000-000000000030' date_emission: '2021-09-15' date_expiration: null statut: a_completer motif: 'Page des signatures des associés manquante : merci de déposer le document complet.' verifie_par: '21000000-0000-4000-8000-000000000003' verifie_le: '2026-08-25T11:15:00Z' cree_le: '2026-08-20T09:40:00Z' modifie_le: '2026-08-25T11:15:00Z' type_document: id: '52000000-0000-4000-8000-000000000003' code: partenaire_statuts libelle: Statuts de la société cible: partenaire obligatoire: true validite_mois: null actif: true fichier: id: '53000000-0000-4000-8000-000000000030' nom_original: Statuts_Émeraude_Systèmes.pdf type_mime: application/pdf taille_octets: 2310253 statut_scan: sain - id: '54000000-0000-4000-8000-000000000025' organisation_id: '20000000-0000-4000-8000-000000000007' type_document_id: '52000000-0000-4000-8000-000000000004' fichier_id: '53000000-0000-4000-8000-000000000031' date_emission: '2016-08-02' date_expiration: '2026-08-01' statut: expire motif: 'Pièce expirée le 01/08/2026 : merci de déposer une pièce en cours de validité.' verifie_par: '21000000-0000-4000-8000-000000000003' verifie_le: '2026-08-25T11:20:00Z' cree_le: '2026-08-20T09:45:00Z' modifie_le: '2026-08-01T00:05:00Z' type_document: id: '52000000-0000-4000-8000-000000000004' code: partenaire_piece_identite libelle: Pièce d'identité du représentant légal cible: partenaire obligatoire: true validite_mois: null actif: true fichier: id: '53000000-0000-4000-8000-000000000031' nom_original: CNI_representant_legal_Émeraude_Systèmes.jpg type_mime: image/jpeg taille_octets: 2383710 statut_scan: sain '401': '$ref': '#/components/responses/NonAuthentifie' '403': '$ref': '#/components/responses/AccesRefuse' '404': '$ref': '#/components/responses/Introuvable' '/api/v1/clients': get: tags: - Clients operationId: listerClients summary: Lister les clients description: "Permission requise : `clients.consulter`. Un partenaire ne voit que ses clients gérés, ses réservations en cours et les fiches qu'il a créées sans partenaire." parameters: - '$ref': '#/components/parameters/Page' - '$ref': '#/components/parameters/Taille' - '$ref': '#/components/parameters/Recherche' - name: statut in: query required: false description: Filtre sur le statut du client. schema: '$ref': '#/components/schemas/StatutClient' - name: statut_kyc in: query required: false description: Filtre sur le statut KYC. schema: '$ref': '#/components/schemas/StatutKyc' - name: partenaire_id in: query required: false description: Clients gérés par ce partenaire. schema: type: string format: uuid - name: secteur_id in: query required: false description: Filtre sur le secteur d'activité. schema: type: string format: uuid responses: '200': description: Page de clients. content: 'application/json': schema: '$ref': '#/components/schemas/PageClients' example: donnees: - id: '40000000-0000-4000-8000-000000000001' organisation_id: '20000000-0000-4000-8000-000000000008' raison_sociale: Clinique Les Palmiers forme_juridique: SA rccm: CI-ABJ-2012-B-04417 ncc: '1204417D' secteur_id: '51000000-0000-4000-8000-000000000004' adresse_facturation: 'Riviera 3, boulevard Mitterrand, Cocody, 01 BP 2140 Abidjan 01' ville: Abidjan zone_id: '50000000-0000-4000-8000-000000000023' telephone: '+225 27 22 47 30 00' email: 'clinique-les-palmiers@demo.novira.ci' origine: partenaire statut: actif statut_kyc: conforme partenaire_actuel_id: '30000000-0000-4000-8000-000000000001' credit_approuve: false plafond_encours: null credit_approuve_par: null cree_par: '21000000-0000-4000-8000-000000000010' cree_le: '2026-06-08T16:30:00Z' modifie_le: '2026-07-22T10:00:00Z' - id: '40000000-0000-4000-8000-000000000002' organisation_id: '20000000-0000-4000-8000-000000000009' raison_sociale: Centre médical Akwaba forme_juridique: SARL rccm: CI-ABJ-2016-B-18820 ncc: '1618820F' secteur_id: '51000000-0000-4000-8000-000000000004' adresse_facturation: 'Yopougon Siporex, rue Princesse, Abidjan' ville: Abidjan zone_id: '50000000-0000-4000-8000-000000000025' telephone: '+225 27 23 45 61 08' email: 'centre-medical-akwaba@demo.novira.ci' origine: partenaire statut: reserve statut_kyc: en_verification partenaire_actuel_id: '30000000-0000-4000-8000-000000000001' credit_approuve: false plafond_encours: null credit_approuve_par: null cree_par: '21000000-0000-4000-8000-000000000010' cree_le: '2026-09-01T11:10:00Z' modifie_le: '2026-09-02T09:05:00Z' pagination: page: 1 taille: 2 total: 11 pages: 6 '401': '$ref': '#/components/responses/NonAuthentifie' '403': '$ref': '#/components/responses/AccesRefuse' '422': '$ref': '#/components/responses/ParametresInvalides' '/api/v1/clients/{id}': get: tags: - Clients operationId: lireClient summary: Lire la fiche d'un client description: 'Permission requise : `clients.consulter`. Inclut le secteur, la zone, le partenaire gestionnaire et les contacts.' parameters: - '$ref': '#/components/parameters/IdClient' responses: '200': description: Fiche du client. content: 'application/json': schema: '$ref': '#/components/schemas/ClientDetail' example: id: '40000000-0000-4000-8000-000000000001' organisation_id: '20000000-0000-4000-8000-000000000008' raison_sociale: Clinique Les Palmiers forme_juridique: SA rccm: CI-ABJ-2012-B-04417 ncc: '1204417D' secteur_id: '51000000-0000-4000-8000-000000000004' adresse_facturation: 'Riviera 3, boulevard Mitterrand, Cocody, 01 BP 2140 Abidjan 01' ville: Abidjan zone_id: '50000000-0000-4000-8000-000000000023' telephone: '+225 27 22 47 30 00' email: 'clinique-les-palmiers@demo.novira.ci' origine: partenaire statut: actif statut_kyc: conforme partenaire_actuel_id: '30000000-0000-4000-8000-000000000001' credit_approuve: false plafond_encours: null credit_approuve_par: null cree_par: '21000000-0000-4000-8000-000000000010' cree_le: '2026-06-08T16:30:00Z' modifie_le: '2026-07-22T10:00:00Z' secteur: id: '51000000-0000-4000-8000-000000000004' code: sante libelle: Santé zone: id: '50000000-0000-4000-8000-000000000023' code: CI-ABJ-COCODY libelle: Cocody type: commune parent_id: '50000000-0000-4000-8000-000000000012' partenaire_actuel: id: '30000000-0000-4000-8000-000000000001' raison_sociale: Akwaba Connect Services ville: Abidjan statut: actif contacts: - id: '41000000-0000-4000-8000-000000000001' client_id: '40000000-0000-4000-8000-000000000001' prenom: Nadège nom: Kouadio fonction: Directrice administrative et financière email: 'nadege.kouadio@demo.novira.ci' telephone: '+225 07 07 63 18 25' principal: true cree_le: '2026-06-08T16:30:00Z' modifie_le: '2026-06-08T16:30:00Z' - id: '41000000-0000-4000-8000-000000000002' client_id: '40000000-0000-4000-8000-000000000001' prenom: Éric nom: Tanoh fonction: Responsable informatique email: 'eric.tanoh@demo.novira.ci' telephone: '+225 05 05 47 32 16' principal: false cree_le: '2026-06-08T16:30:00Z' modifie_le: '2026-06-08T16:30:00Z' - id: '41000000-0000-4000-8000-000000000003' client_id: '40000000-0000-4000-8000-000000000001' prenom: Paul-Henri nom: Yapi fonction: Directeur médical email: 'paul-henri.yapi@demo.novira.ci' telephone: '+225 07 09 81 22 64' principal: false cree_le: '2026-06-08T16:30:00Z' modifie_le: '2026-06-08T16:30:00Z' '401': '$ref': '#/components/responses/NonAuthentifie' '403': '$ref': '#/components/responses/AccesRefuse' '404': '$ref': '#/components/responses/Introuvable' '/api/v1/clients/{id}/sites': get: tags: - Clients operationId: listerSitesClient summary: Lister les sites d'un client description: 'Permission requise : `clients.consulter`. Un client peut avoir plusieurs sites ; chaque site reçoit une antenne dédiée.' parameters: - '$ref': '#/components/parameters/IdClient' responses: '200': description: 'Sites du client. Exemple : un client sur trois sites.' content: 'application/json': schema: '$ref': '#/components/schemas/ListeSites' example: donnees: - id: '42000000-0000-4000-8000-000000000008' client_id: '40000000-0000-4000-8000-000000000006' libelle: Siège · Plateau adresse: 'Avenue Chardy, immeuble Alpha 2000, Plateau' ville: Abidjan zone_id: '50000000-0000-4000-8000-000000000024' latitude: 5.3228 longitude: -4.0183 contact_id: '41000000-0000-4000-8000-000000000010' statut: actif cree_le: '2026-06-30T10:20:00Z' modifie_le: '2026-07-20T10:00:00Z' - id: '42000000-0000-4000-8000-000000000009' client_id: '40000000-0000-4000-8000-000000000006' libelle: Agence de Yopougon adresse: 'Carrefour Siporex, Yopougon' ville: Abidjan zone_id: '50000000-0000-4000-8000-000000000025' latitude: 5.3504 longitude: -4.0826 contact_id: '41000000-0000-4000-8000-000000000010' statut: suspendu cree_le: '2026-06-30T10:20:00Z' modifie_le: '2026-08-26T08:30:00Z' - id: '42000000-0000-4000-8000-000000000010' client_id: '40000000-0000-4000-8000-000000000006' libelle: Agence de San-Pédro adresse: 'Boulevard de la Paix, quartier Bardot' ville: San-Pédro zone_id: '50000000-0000-4000-8000-000000000017' latitude: 4.7474 longitude: -6.6425 contact_id: '41000000-0000-4000-8000-000000000011' statut: a_installer cree_le: '2026-06-30T10:20:00Z' modifie_le: '2026-09-07T11:30:00Z' '401': '$ref': '#/components/responses/NonAuthentifie' '403': '$ref': '#/components/responses/AccesRefuse' '404': '$ref': '#/components/responses/Introuvable' '/api/v1/reservations': get: tags: - Réservations operationId: listerReservations summary: Lister les réservations description: 'Permission requise : `clients.consulter`. La validation ou le refus exige `clients.reservation_valider`. Les demandes en attente (`demandee`, `conflit`) sont renvoyées en premier.' parameters: - '$ref': '#/components/parameters/Page' - '$ref': '#/components/parameters/Taille' - name: statut in: query required: false description: Filtre sur le statut. schema: '$ref': '#/components/schemas/StatutReservation' - name: partenaire_id in: query required: false description: Réservations de ce partenaire. schema: type: string format: uuid - name: client_id in: query required: false description: Réservations portant sur ce client. schema: type: string format: uuid responses: '200': description: 'Page de réservations. Exemple : un doublon potentiel et un conflit entre deux partenaires.' content: 'application/json': schema: '$ref': '#/components/schemas/PageReservations' example: donnees: - id: '43000000-0000-4000-8000-000000000013' client_id: '40000000-0000-4000-8000-000000000011' partenaire_id: '30000000-0000-4000-8000-000000000002' demandee_par: '21000000-0000-4000-8000-000000000013' statut: demandee doublons_detectes: resultat: doublon_potentiel controle_le: '2026-09-15T09:40:00Z' correspondances: - client_id: '40000000-0000-4000-8000-000000000001' raison_sociale: Clinique Les Palmiers partenaire_actuel_id: '30000000-0000-4000-8000-000000000001' criteres: - raison_sociale_proche - telephone_identique - email_contact_identique similarite: 0.82 reservations_concurrentes: [] motif_decision: null traitee_par: null traitee_le: null cree_le: '2026-09-15T09:40:00Z' modifie_le: '2026-09-15T09:40:00Z' - id: '43000000-0000-4000-8000-000000000005' client_id: '40000000-0000-4000-8000-000000000005' partenaire_id: '30000000-0000-4000-8000-000000000002' demandee_par: '21000000-0000-4000-8000-000000000013' statut: conflit doublons_detectes: resultat: conflit controle_le: '2026-09-12T08:47:00Z' correspondances: [] reservations_concurrentes: - reservation_id: '43000000-0000-4000-8000-000000000006' partenaire_id: '30000000-0000-4000-8000-000000000001' demandee_le: '2026-09-12T08:47:00Z' motif_decision: null traitee_par: null traitee_le: null cree_le: '2026-09-11T10:12:00Z' modifie_le: '2026-09-11T10:12:00Z' pagination: page: 1 taille: 2 total: 13 pages: 7 '401': '$ref': '#/components/responses/NonAuthentifie' '403': '$ref': '#/components/responses/AccesRefuse' '422': '$ref': '#/components/responses/ParametresInvalides' '/api/v1/offres': get: tags: - Catalogue operationId: listerOffres summary: Lister les offres et leur tarif en vigueur description: 'Permission requise : `catalogue.consulter`. Le tarif renvoyé est celui en vigueur à la date du jour ; un devis déjà émis conserve son prix.' parameters: - '$ref': '#/components/parameters/Page' - '$ref': '#/components/parameters/Taille' - name: periode in: query required: false description: Filtre sur la période du forfait. schema: '$ref': '#/components/schemas/PeriodeForfait' - name: volume_go in: query required: false description: Filtre sur le volume en Go. schema: type: integer minimum: 1 - name: actif in: query required: false description: Offres proposées à la vente uniquement. schema: type: boolean responses: '200': description: Page d'offres. content: 'application/json': schema: '$ref': '#/components/schemas/PageOffres' example: donnees: - id: '61000000-0000-4000-8000-000000000015' produit_id: '60000000-0000-4000-8000-000000000005' code: DATA-250GO-AN libelle: Forfait 250 Go annuel volume_go: 250 periode: annuelle debit: Selon capacité nb_appareils: 40 nb_acces: 2 actif: true cree_le: '2026-09-15T16:15:00Z' modifie_le: '2026-09-15T16:15:00Z' tarif_en_vigueur: id: '62000000-0000-4000-8000-000000000015' produit_id: '60000000-0000-4000-8000-000000000005' offre_id: '61000000-0000-4000-8000-000000000015' prix_ht: 2140000 valide_du: '2026-09-01' valide_au: null cree_par: '21000000-0000-4000-8000-000000000002' cree_le: '2026-08-28T10:00:00Z' - id: '61000000-0000-4000-8000-000000000020' produit_id: '60000000-0000-4000-8000-000000000005' code: DATA-500GO-AN libelle: Forfait 500 Go annuel volume_go: 500 periode: annuelle debit: Selon capacité nb_appareils: 80 nb_acces: 3 actif: true cree_le: '2026-09-15T16:15:00Z' modifie_le: '2026-09-15T16:15:00Z' tarif_en_vigueur: id: '62000000-0000-4000-8000-000000000021' produit_id: '60000000-0000-4000-8000-000000000005' offre_id: '61000000-0000-4000-8000-000000000020' prix_ht: 3670000 valide_du: '2026-09-01' valide_au: null cree_par: '21000000-0000-4000-8000-000000000002' cree_le: '2026-08-28T10:00:00Z' pagination: page: 1 taille: 2 total: 25 pages: 13 '401': '$ref': '#/components/responses/NonAuthentifie' '403': '$ref': '#/components/responses/AccesRefuse' '422': '$ref': '#/components/responses/ParametresInvalides' components: securitySchemes: jetonAcces: type: http scheme: bearer bearerFormat: JWT description: Jeton d'accès Supabase Auth obtenu après connexion par e-mail. parameters: Page: name: page in: query required: false description: 'Numéro de page, à partir de 1.' schema: type: integer minimum: 1 default: 1 Taille: name: taille in: query required: false description: Nombre d'éléments par page. schema: type: integer minimum: 1 maximum: 100 default: 20 Recherche: name: recherche in: query required: false description: 'Recherche plein texte sur la raison sociale, le RCCM ou le NCC (insensible aux accents et à la casse).' schema: type: string minLength: 2 maxLength: 100 IdPartenaire: name: id in: path required: true description: Identifiant du partenaire. schema: type: string format: uuid IdClient: name: id in: path required: true description: Identifiant du client. schema: type: string format: uuid responses: NonAuthentifie: description: 'Jeton absent, expiré ou invalide.' content: 'application/json': schema: '$ref': '#/components/schemas/Erreur' example: code: authentification_requise message: Votre session a expiré. Merci de vous reconnecter. details: null AccesRefuse: description: Permission manquante ou donnée hors du périmètre de votre organisation. content: 'application/json': schema: '$ref': '#/components/schemas/Erreur' example: code: acces_refuse message: Vous n'avez pas les droits nécessaires pour cette action. details: permission_requise: partenaires.consulter Introuvable: description: "Ressource inexistante ou non visible avec vos droits : l'API ne distingue pas les deux cas." content: 'application/json': schema: '$ref': '#/components/schemas/Erreur' example: code: ressource_introuvable message: Cet élément n'existe pas ou n'est pas accessible avec vos droits. details: null ParametresInvalides: description: Paramètres de requête invalides. content: 'application/json': schema: '$ref': '#/components/schemas/Erreur' example: code: parametres_invalides message: Certains paramètres sont invalides. details: taille: La taille de page doit être comprise entre 1 et 100. schemas: Erreur: type: object description: Format unique des erreurs renvoyées par l'API. required: - code - message - details properties: code: type: string description: 'Code stable, en snake_case, destiné au programme appelant.' examples: - partenaire_introuvable message: type: string description: "Message en français, prêt à être affiché à l'utilisateur." details: type: - object - array - 'null' description: 'Précisions facultatives : champ en cause, valeur attendue, liste des erreurs de validation.' Pagination: type: object description: Position dans une liste paginée. required: - page - taille - total - pages properties: page: type: integer description: 'Numéro de la page renvoyée, à partir de 1.' minimum: 1 taille: type: integer description: Nombre maximal d'éléments par page. minimum: 1 maximum: 100 total: type: integer description: Nombre total d'éléments correspondant aux filtres. minimum: 0 pages: type: integer description: Nombre total de pages. minimum: 0 Sante: type: object description: État du service. required: - statut - version - horodatage properties: statut: type: string enum: - ok - degrade description: '`ok` : service disponible ; `degrade` : une dépendance répond mal.' version: type: string description: Version de l'API déployée. horodatage: type: string format: date-time description: Heure du serveur (UTC). TypeOrganisation: type: string enum: - cybastion - partenaire - client - vipnet description: |- Type d'organisation. - `cybastion` : CYBASTION - `partenaire` : Partenaire - `client` : Client - `vipnet` : VIP Net StatutOrganisation: type: string enum: - active - suspendue - fermee description: |- Statut d'une organisation. - `active` : Active - `suspendue` : Suspendue - `fermee` : Fermée StatutPartenaire: type: string enum: - candidat - en_verification - a_completer - rejete - valide - actif - suspendu description: |- Statut de référencement du partenaire. - `candidat` : Candidat - `en_verification` : En vérification - `a_completer` : À compléter - `rejete` : Rejeté - `valide` : Validé - `actif` : Actif - `suspendu` : Suspendu ModeVersement: type: string enum: - virement - mobile_money - wave description: |- Mode de versement des commissions. - `virement` : Virement bancaire - `mobile_money` : Mobile Money - `wave` : Wave StatutContratCadre: type: string enum: - genere - envoye - signe - expire - resilie description: |- Statut du contrat-cadre. - `genere` : Généré - `envoye` : Envoyé - `signe` : Signé - `expire` : Expiré - `resilie` : Résilié OrigineClient: type: string enum: - partenaire - direct - import description: |- Origine du client. - `partenaire` : Apporté par un partenaire - `direct` : Venu en direct - `import` : Importé StatutClient: type: string enum: - prospect - reservation_demandee - reserve - actif - inactif description: |- Statut du client. - `prospect` : Prospect - `reservation_demandee` : Réservation demandée - `reserve` : Réservé - `actif` : Actif - `inactif` : Inactif StatutKyc: type: string enum: - a_fournir - en_verification - conforme - a_completer - rejete description: |- Statut du dossier KYC du client. - `a_fournir` : À fournir - `en_verification` : En vérification - `conforme` : Conforme - `a_completer` : À compléter - `rejete` : Rejeté StatutSite: type: string enum: - a_qualifier - a_installer - installe - actif - suspendu - resilie description: |- Statut du site. - `a_qualifier` : À qualifier - `a_installer` : À installer - `installe` : Installé - `actif` : Actif - `suspendu` : Suspendu - `resilie` : Résilié StatutReservation: type: string enum: - demandee - conflit - validee - refusee - annulee description: |- Statut de la réservation. - `demandee` : À valider - `conflit` : Conflit à arbitrer - `validee` : Validée - `refusee` : Refusée - `annulee` : Annulée StatutDocument: type: string enum: - depose - valide - a_completer - rejete - expire description: |- Statut de la pièce. - `depose` : En attente - `valide` : Validé - `a_completer` : À compléter - `rejete` : Rejeté - `expire` : Expiré StatutScan: type: string enum: - en_attente - sain - infecte description: |- Résultat de l'analyse antivirus. - `en_attente` : Analyse en cours - `sain` : Aucune menace - `infecte` : Fichier bloqué CibleDocument: type: string enum: - partenaire - client description: |- Organisation concernée par le type de pièce. - `partenaire` : Partenaire - `client` : Client TypeZone: type: string enum: - region - departement - ville - commune description: |- Niveau de la zone géographique. - `region` : Région - `departement` : Département - `ville` : Ville - `commune` : Commune PeriodeForfait: type: string enum: - hebdomadaire - mensuelle - trimestrielle - semestrielle - annuelle description: |- Période du forfait data. - `hebdomadaire` : Hebdomadaire - `mensuelle` : Mensuelle - `trimestrielle` : Trimestrielle - `semestrielle` : Semestrielle - `annuelle` : Annuelle Organisation: type: object description: 'Entité qui utilise la plateforme : CYBASTION, partenaire, client ou VIP Net.' required: - id - type - nom - statut - cree_le - modifie_le properties: id: type: string format: uuid description: Identifiant de l'organisation. type: '$ref': '#/components/schemas/TypeOrganisation' nom: type: string description: Nom usuel de l'organisation. statut: '$ref': '#/components/schemas/StatutOrganisation' cree_le: type: string format: date-time description: Date de création. modifie_le: type: string format: date-time description: Date de dernière modification. RoleAttribue: type: object description: Rôle attribué à l'utilisateur. Un utilisateur peut en cumuler plusieurs. required: - code - libelle - type_organisation - principal properties: code: type: string description: Code du rôle. examples: - cybastion_finance libelle: type: string description: Libellé du rôle. type_organisation: '$ref': '#/components/schemas/TypeOrganisation' principal: type: boolean description: 'Vrai pour le rôle principal (`utilisateurs.role_id`).' Utilisateur: type: object description: Personne connectée. Son identifiant est celui du compte Supabase Auth. required: - id - organisation_id - role_id - prenom - nom - email - telephone - fonction - actif - double_authentification - derniere_connexion properties: id: type: string format: uuid description: Identifiant de l'utilisateur (identique au compte d'authentification). organisation_id: type: string format: uuid description: Organisation de rattachement. role_id: type: string format: uuid description: Rôle principal. prenom: type: string description: Prénom. nom: type: string description: Nom. email: type: - string - 'null' description: Adresse e-mail de connexion. format: email telephone: type: - string - 'null' description: Téléphone au format +225. fonction: type: - string - 'null' description: Fonction dans l'organisation. actif: type: boolean description: Faux dès que le compte ou l'organisation est suspendu. double_authentification: type: boolean description: Double authentification activée (obligatoire pour CYBASTION). derniere_connexion: type: - string - 'null' format: date-time description: Dernière connexion. Moi: type: object description: Session de l'utilisateur connecté. required: - utilisateur - organisation - roles - permissions properties: utilisateur: '$ref': '#/components/schemas/Utilisateur' organisation: '$ref': '#/components/schemas/Organisation' roles: type: array items: '$ref': '#/components/schemas/RoleAttribue' description: Ensemble des rôles attribués. permissions: type: array items: type: string uniqueItems: true description: "Union des permissions de tous les rôles. Les interfaces n'affichent un menu, un écran ou un bouton que si la permission correspondante figure ici." ZoneGeographique: type: object description: 'Territoire hiérarchisé (région, ville, commune).' required: - id - code - libelle - type - parent_id properties: id: type: string format: uuid description: Identifiant de la zone. code: type: string description: Code de la zone. libelle: type: string description: Nom affiché. type: '$ref': '#/components/schemas/TypeZone' parent_id: type: - string - 'null' format: uuid description: Zone parente. SecteurActivite: type: object description: Secteur d'activité. required: - id - code - libelle properties: id: type: string format: uuid description: Identifiant du secteur. code: type: string description: Code du secteur. libelle: type: string description: Libellé affiché. Partenaire: type: object description: Entreprise distributrice référencée par CYBASTION. required: - id - organisation_id - raison_sociale - forme_juridique - rccm - ncc - adresse - ville - zone_principale_id - telephone - email - capacite_commerciale - mode_versement - rib - numero_mobile_money - logo_fichier_id - presentation - profil_publie - statut - valide_par - valide_le - cree_le - modifie_le properties: id: type: string format: uuid description: Identifiant du partenaire. organisation_id: type: string format: uuid description: Organisation du partenaire. raison_sociale: type: string description: Raison sociale. forme_juridique: type: - string - 'null' description: 'Forme juridique (SARL, SA…).' rccm: type: - string - 'null' description: Numéro au registre du commerce. ncc: type: - string - 'null' description: Numéro de compte contribuable. adresse: type: - string - 'null' description: Adresse. ville: type: - string - 'null' description: Ville. zone_principale_id: type: - string - 'null' format: uuid description: Zone principale. telephone: type: - string - 'null' description: Téléphone. email: type: - string - 'null' description: E-mail de contact. capacite_commerciale: type: - integer - 'null' description: Nombre de commerciaux. minimum: 0 mode_versement: '$ref': '#/components/schemas/ModeVersement' rib: type: - string - 'null' description: Relevé d'identité bancaire (versement par virement). numero_mobile_money: type: - string - 'null' description: Numéro de versement mobile. logo_fichier_id: type: - string - 'null' format: uuid description: Logo utilisé en co-branding des devis. presentation: type: - string - 'null' description: Profil public visible des clients après modération. profil_publie: type: boolean description: Profil public publié. statut: '$ref': '#/components/schemas/StatutPartenaire' valide_par: type: - string - 'null' format: uuid description: Utilisateur CYBASTION ayant activé le partenaire. valide_le: type: - string - 'null' format: date-time description: Date d'activation. cree_le: type: string format: date-time description: Date de création. modifie_le: type: string format: date-time description: Date de dernière modification. ContratCadre: type: object description: Contrat-cadre signé avec le partenaire. required: - id - numero - partenaire_id - conditions_id - fichier_genere_id - fichier_signe_id - statut - date_debut - date_fin - signe_le - cree_le - modifie_le properties: id: type: string format: uuid description: Identifiant du contrat-cadre. numero: type: string description: Numéro du contrat-cadre. partenaire_id: type: string format: uuid description: Partenaire. conditions_id: type: string format: uuid description: Conditions commerciales acceptées. fichier_genere_id: type: string format: uuid description: Document généré. fichier_signe_id: type: - string - 'null' format: uuid description: Document signé. statut: '$ref': '#/components/schemas/StatutContratCadre' date_debut: type: - string - 'null' format: date description: Début de validité. date_fin: type: - string - 'null' format: date description: Fin de validité. signe_le: type: - string - 'null' format: date-time description: Date de signature. cree_le: type: string format: date-time description: Date de création. modifie_le: type: string format: date-time description: Date de dernière modification. PartenaireResume: type: object description: 'Résumé du partenaire, pour les listes et les rattachements.' required: - id - raison_sociale - ville - statut properties: id: type: string format: uuid description: Identifiant du partenaire. raison_sociale: type: string description: Raison sociale. ville: type: - string - 'null' description: Ville. statut: '$ref': '#/components/schemas/StatutPartenaire' PartenaireDetail: description: Fiche complète du partenaire. allOf: - '$ref': '#/components/schemas/Partenaire' - type: object description: Rattachements de la fiche. required: - zones - secteurs - contrat_cadre properties: zones: type: array items: '$ref': '#/components/schemas/ZoneGeographique' description: Zones couvertes. secteurs: type: array items: '$ref': '#/components/schemas/SecteurActivite' description: Secteurs ciblés. contrat_cadre: oneOf: - '$ref': '#/components/schemas/ContratCadre' - type: 'null' TypeDocument: type: object description: Pièce exigée. required: - id - code - libelle - cible - obligatoire - validite_mois - actif properties: id: type: string format: uuid description: Identifiant du type. code: type: string description: Code du type. libelle: type: string description: Libellé affiché. cible: '$ref': '#/components/schemas/CibleDocument' obligatoire: type: boolean description: Pièce obligatoire. validite_mois: type: - integer - 'null' description: Durée de validité en mois. actif: type: boolean description: Type utilisé. FichierResume: type: object description: Fichier stocké de manière privée ; le contenu se télécharge par lien signé à durée courte. required: - id - nom_original - type_mime - taille_octets - statut_scan properties: id: type: string format: uuid description: Identifiant du fichier. nom_original: type: string description: Nom du fichier déposé. type_mime: type: string description: Type MIME. taille_octets: type: integer description: Taille en octets. minimum: 0 statut_scan: '$ref': '#/components/schemas/StatutScan' DocumentKyc: type: object description: Pièce KYC déposée et vérifiée par la Compliance. required: - id - organisation_id - type_document_id - fichier_id - date_emission - date_expiration - statut - motif - verifie_par - verifie_le - cree_le - modifie_le - type_document - fichier properties: id: type: string format: uuid description: Identifiant de la pièce. organisation_id: type: string format: uuid description: Organisation concernée. type_document_id: type: string format: uuid description: Type de pièce. fichier_id: type: string format: uuid description: Fichier. date_emission: type: - string - 'null' format: date description: Date d'émission. date_expiration: type: - string - 'null' format: date description: Date d'expiration ; la pièce passe automatiquement en « expiré ». statut: '$ref': '#/components/schemas/StatutDocument' motif: type: - string - 'null' description: "Motif du rejet, du complément demandé ou de l'expiration." verifie_par: type: - string - 'null' format: uuid description: Vérificateur. verifie_le: type: - string - 'null' format: date-time description: Date de vérification. cree_le: type: string format: date-time description: Date de dépôt. modifie_le: type: string format: date-time description: Date de dernière modification. type_document: '$ref': '#/components/schemas/TypeDocument' fichier: '$ref': '#/components/schemas/FichierResume' Client: type: object description: 'Entreprise cliente, fiche unique grâce au contrôle de doublon.' required: - id - organisation_id - raison_sociale - forme_juridique - rccm - ncc - secteur_id - adresse_facturation - ville - zone_id - telephone - email - origine - statut - statut_kyc - partenaire_actuel_id - credit_approuve - plafond_encours - credit_approuve_par - cree_par - cree_le - modifie_le properties: id: type: string format: uuid description: Identifiant du client. organisation_id: type: string format: uuid description: Organisation du client. raison_sociale: type: string description: Raison sociale. forme_juridique: type: - string - 'null' description: Forme juridique. rccm: type: - string - 'null' description: Numéro RCCM. ncc: type: - string - 'null' description: Numéro de compte contribuable. secteur_id: type: - string - 'null' format: uuid description: Secteur d'activité. adresse_facturation: type: - string - 'null' description: Adresse de facturation. ville: type: - string - 'null' description: Ville. zone_id: type: - string - 'null' format: uuid description: Zone géographique. telephone: type: - string - 'null' description: Téléphone. email: type: - string - 'null' description: E-mail. origine: '$ref': '#/components/schemas/OrigineClient' statut: '$ref': '#/components/schemas/StatutClient' statut_kyc: '$ref': '#/components/schemas/StatutKyc' partenaire_actuel_id: type: - string - 'null' format: uuid description: "Partenaire gestionnaire, recopié de l'affectation active." credit_approuve: type: boolean description: Client autorisé au postpayé. plafond_encours: type: - number - 'null' minimum: 0 description: "Plafond d'encours autorisé. En francs CFA (XOF), sans décimale." credit_approuve_par: type: - string - 'null' format: uuid description: Approbateur du crédit. cree_par: type: - string - 'null' format: uuid description: Créateur de la fiche. cree_le: type: string format: date-time description: Date de création. modifie_le: type: string format: date-time description: Date de dernière modification. Contact: type: object description: Interlocuteur de l'entreprise cliente. required: - id - client_id - prenom - nom - fonction - email - telephone - principal - cree_le - modifie_le properties: id: type: string format: uuid description: Identifiant du contact. client_id: type: string format: uuid description: Client. prenom: type: string description: Prénom. nom: type: string description: Nom. fonction: type: - string - 'null' description: Fonction. email: type: - string - 'null' description: E-mail. telephone: type: - string - 'null' description: Téléphone. principal: type: boolean description: Contact principal (un seul par client). cree_le: type: string format: date-time description: Date de création. modifie_le: type: string format: date-time description: Date de dernière modification. ClientDetail: description: Fiche complète du client. allOf: - '$ref': '#/components/schemas/Client' - type: object description: Rattachements de la fiche. required: - secteur - zone - partenaire_actuel - contacts properties: secteur: oneOf: - '$ref': '#/components/schemas/SecteurActivite' - type: 'null' zone: oneOf: - '$ref': '#/components/schemas/ZoneGeographique' - type: 'null' partenaire_actuel: oneOf: - '$ref': '#/components/schemas/PartenaireResume' - type: 'null' contacts: type: array items: '$ref': '#/components/schemas/Contact' description: 'Interlocuteurs, contact principal en premier.' Site: type: object description: Lieu physique du client ; chaque site reçoit une antenne dédiée. required: - id - client_id - libelle - adresse - ville - zone_id - latitude - longitude - contact_id - statut - cree_le - modifie_le properties: id: type: string format: uuid description: Identifiant du site. client_id: type: string format: uuid description: Client. libelle: type: string description: Libellé du site. adresse: type: - string - 'null' description: Adresse. ville: type: - string - 'null' description: Ville. zone_id: type: - string - 'null' format: uuid description: Zone géographique. latitude: type: - number - 'null' minimum: -90 maximum: 90 description: Latitude GPS. longitude: type: - number - 'null' minimum: -180 maximum: 180 description: Longitude GPS. contact_id: type: - string - 'null' format: uuid description: Contact sur site. statut: '$ref': '#/components/schemas/StatutSite' cree_le: type: string format: date-time description: Date de création. modifie_le: type: string format: date-time description: Date de dernière modification. ControleDoublon: type: object description: Résultat du contrôle de doublon réalisé à la demande de réservation. required: - resultat - controle_le - correspondances - reservations_concurrentes properties: resultat: type: string enum: - aucun - doublon_potentiel - conflit description: |- - `aucun` : Aucun doublon - `doublon_potentiel` : Doublon potentiel - `conflit` : Autre partenaire sur ce client controle_le: type: string format: date-time description: Date du contrôle. correspondances: type: array description: Fiches clients proches. items: type: object description: Fiche proche. required: - client_id - raison_sociale - partenaire_actuel_id - criteres - similarite properties: client_id: type: string format: uuid description: Client déjà connu. raison_sociale: type: string description: Raison sociale du client déjà connu. partenaire_actuel_id: type: - string - 'null' format: uuid description: Son partenaire actuel. criteres: type: array items: type: string enum: - raison_sociale_proche - telephone_identique - email_contact_identique - rccm_identique - ncc_identique description: Critères concordants. similarite: type: number minimum: 0 maximum: 1 description: Similarité de la raison sociale (0 à 1). reservations_concurrentes: type: array description: Réservations d'autres partenaires sur le même client. items: type: object description: Réservation concurrente. required: - reservation_id - partenaire_id - demandee_le properties: reservation_id: type: string format: uuid description: Réservation concurrente. partenaire_id: type: string format: uuid description: Partenaire concurrent. demandee_le: type: string format: date-time description: Date de la demande concurrente. Reservation: type: object description: Demande d'un partenaire pour se voir attribuer un client ; effective après validation CYBASTION. required: - id - client_id - partenaire_id - demandee_par - statut - doublons_detectes - motif_decision - traitee_par - traitee_le - cree_le - modifie_le properties: id: type: string format: uuid description: Identifiant de la réservation. client_id: type: string format: uuid description: Client. partenaire_id: type: string format: uuid description: Partenaire demandeur. demandee_par: type: string format: uuid description: Utilisateur demandeur. statut: '$ref': '#/components/schemas/StatutReservation' doublons_detectes: oneOf: - '$ref': '#/components/schemas/ControleDoublon' - type: 'null' motif_decision: type: - string - 'null' description: Motif du refus ou de l'annulation. traitee_par: type: - string - 'null' format: uuid description: Utilisateur ayant tranché. traitee_le: type: - string - 'null' format: date-time description: Date de décision. cree_le: type: string format: date-time description: Date de la demande. modifie_le: type: string format: date-time description: Date de dernière modification. Tarif: type: object description: "Prix HT daté d'un produit ou d'une offre ; recopié dans le devis, jamais recalculé." required: - id - produit_id - offre_id - prix_ht - valide_du - valide_au - cree_par - cree_le properties: id: type: string format: uuid description: Identifiant du tarif. produit_id: type: string format: uuid description: Produit. offre_id: type: - string - 'null' format: uuid description: Offre. prix_ht: type: number minimum: 0 description: 'Prix unitaire hors taxes. En francs CFA (XOF), sans décimale.' valide_du: type: string format: date description: Début de validité. valide_au: type: - string - 'null' format: date description: 'Fin de validité (vide : sans limite).' cree_par: type: string format: uuid description: Auteur. cree_le: type: string format: date-time description: Date de création. Offre: type: object description: Forfait data défini par son volume et sa période. required: - id - produit_id - code - libelle - volume_go - periode - debit - nb_appareils - nb_acces - actif - cree_le - modifie_le - tarif_en_vigueur properties: id: type: string format: uuid description: Identifiant de l'offre. produit_id: type: string format: uuid description: Produit (forfait data). code: type: string description: Code de l'offre. libelle: type: string description: Libellé affiché. volume_go: type: integer description: Volume en Go (1 To = 1000 Go). minimum: 1 periode: '$ref': '#/components/schemas/PeriodeForfait' debit: type: - string - 'null' description: Débit annoncé. nb_appareils: type: - integer - 'null' description: Nombre d'appareils connectables. minimum: 0 nb_acces: type: - integer - 'null' description: Nombre d'accès. minimum: 0 actif: type: boolean description: Offre proposée à la vente. cree_le: type: string format: date-time description: Date de création. modifie_le: type: string format: date-time description: Date de dernière modification. tarif_en_vigueur: oneOf: - '$ref': '#/components/schemas/Tarif' - type: 'null' PagePartenaires: type: object description: Page de partenaires. required: - donnees - pagination properties: donnees: type: array items: '$ref': '#/components/schemas/Partenaire' pagination: '$ref': '#/components/schemas/Pagination' PageClients: type: object description: Page de clients. required: - donnees - pagination properties: donnees: type: array items: '$ref': '#/components/schemas/Client' pagination: '$ref': '#/components/schemas/Pagination' PageReservations: type: object description: Page de réservations. required: - donnees - pagination properties: donnees: type: array items: '$ref': '#/components/schemas/Reservation' pagination: '$ref': '#/components/schemas/Pagination' PageOffres: type: object description: Page d'offres. required: - donnees - pagination properties: donnees: type: array items: '$ref': '#/components/schemas/Offre' pagination: '$ref': '#/components/schemas/Pagination' ListeDocumentsKyc: type: object description: Pièces KYC du partenaire. required: - donnees properties: donnees: type: array items: '$ref': '#/components/schemas/DocumentKyc' ListeSites: type: object description: Sites du client. required: - donnees properties: donnees: type: array items: '$ref': '#/components/schemas/Site'