{"openapi":"3.0.3","info":{"title":"Ujumbe RDC API","description":"API REST pour l'envoi de SMS, gestion de contacts, campagnes, templates, liens courts et portefeuille. Conçue pour le marché congolais (Vodacom, Airtel, Orange, Africell).","version":"1.0.0","contact":{"name":"Support Ujumbe RDC","email":"support@ujumbe.cd","url":"https://ujumbe.cd"}},"servers":[{"url":"/api/v1","description":"Serveur courant (même origine)"},{"url":"https://api.ujumbe.cd/v1","description":"Serveur de production"}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","bearerFormat":"API key","description":"Clé API obtenue depuis Tableau de bord → Développeurs & API, envoyée avec Authorization: Bearer <clé>"}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"string","description":"Message d'erreur"}}}}},"paths":{"/sms/send":{"post":{"tags":["SMS"],"summary":"Envoyer un SMS","description":"Achemine un SMS individuel vers un numéro congolais (Vodacom, Airtel, Orange, Africell). Débite automatiquement les crédits SMS du compte.","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["to","message"],"properties":{"to":{"type":"string","description":"Numéro de téléphone congolais (format national ou E.164)","example":"+243819876543"},"message":{"type":"string","description":"Contenu du SMS (max 160 caractères GSM-7 par segment)","example":"Votre code OTP est: 849201"},"senderId":{"type":"string","description":"Nom d'émetteur approuvé (max 11 caractères)","example":"BOUTIQUE_K"}}}}}},"responses":{"200":{"description":"SMS envoyé avec succès","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"messageId":{"type":"string","example":"ujm_msg_9847291048"},"provider":{"type":"string","example":"ONES2U"},"status":{"type":"string","example":"SENT"}}}}}},"401":{"description":"Clé API invalide ou manquante","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Erreur serveur interne","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"tags":["SMS"],"summary":"Historique des messages","description":"Retourne la liste paginée des SMS envoyés par l'organisation, triés du plus récent au plus ancien.","security":[{"apiKey":[]}],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":50},"description":"Nombre de résultats par page"},{"name":"offset","in":"query","schema":{"type":"integer","default":0},"description":"Décalage pour la pagination"}],"responses":{"200":{"description":"Liste des messages","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"messages":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"recipientPhone":{"type":"string"},"messageContent":{"type":"string"},"status":{"type":"string"},"carrier":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}}},"total":{"type":"integer"}}}}}},"401":{"description":"Non autorisé","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Erreur serveur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/campaigns":{"get":{"tags":["Campagnes"],"summary":"Lister les campagnes","description":"Retourne toutes les campagnes SMS de l'organisation triées par date de création décroissante.","security":[{"apiKey":[]}],"responses":{"200":{"description":"Liste des campagnes","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"campaigns":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"message":{"type":"string"},"status":{"type":"string","enum":["DRAFT","SCHEDULED","SENDING","COMPLETED","FAILED"]},"totalRecipients":{"type":"integer"},"deliveredCount":{"type":"integer"},"creditsCost":{"type":"integer"},"createdAt":{"type":"string","format":"date-time"}}}}}}}}},"401":{"description":"Non autorisé","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Erreur serveur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["Campagnes"],"summary":"Créer une campagne","description":"Lance ou planifie une campagne SMS de masse vers vos contacts.","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["title","message"],"properties":{"title":{"type":"string","description":"Titre de la campagne","example":"Promo Août 2026"},"message":{"type":"string","description":"Texte du SMS","example":"Profitez de -30% ce weekend!"},"senderId":{"type":"string","description":"Nom d'émetteur","example":"BOUTIQUE_K"},"scheduledAt":{"type":"string","format":"date-time","description":"Date de planification ISO 8601 (optionnel, envoi immédiat si absent)","example":"2026-09-01T09:00:00Z"},"targetFilter":{"type":"object","description":"Filtre d'audience","properties":{"type":{"type":"string","enum":["ALL","GROUP","CARRIER"]},"groupId":{"type":"string"},"carrier":{"type":"string","enum":["VODACOM","AIRTEL","ORANGE","AFRICELL"]}}}}}}}},"responses":{"200":{"description":"Campagne créée et transmise","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"},"campaign":{"type":"object"}}}}}},"401":{"description":"Non autorisé","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Erreur serveur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/contacts":{"get":{"tags":["Contacts"],"summary":"Lister les contacts","description":"Retourne tous les contacts de l'organisation avec possibilité de filtrer par groupe ou opérateur.","security":[{"apiKey":[]}],"parameters":[{"name":"groupId","in":"query","schema":{"type":"string"},"description":"Filtrer par groupe"},{"name":"carrier","in":"query","schema":{"type":"string"},"description":"Filtrer par opérateur"},{"name":"limit","in":"query","schema":{"type":"integer","default":100}},{"name":"offset","in":"query","schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"Liste des contacts","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"contacts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"phone":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"carrier":{"type":"string"},"city":{"type":"string"}}}},"total":{"type":"integer"}}}}}},"401":{"description":"Non autorisé","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Erreur serveur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["Contacts"],"summary":"Ajouter un contact","description":"Crée un nouveau contact dans l'organisation. Le numéro de téléphone est normalisé automatiquement.","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["phone"],"properties":{"phone":{"type":"string","example":"+243819876543"},"firstName":{"type":"string","example":"Jean-Pierre"},"lastName":{"type":"string","example":"Kabila"},"city":{"type":"string","example":"Kinshasa"},"groupId":{"type":"string","description":"ID du groupe à assigner"}}}}}},"responses":{"200":{"description":"Contact créé","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"contact":{"type":"object"}}}}}},"401":{"description":"Non autorisé","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Erreur serveur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/balance":{"get":{"tags":["Portefeuille"],"summary":"Consulter le solde","description":"Retourne le solde actuel du portefeuille en USD et le nombre de crédits SMS disponibles.","security":[{"apiKey":[]}],"responses":{"200":{"description":"Solde actuel","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"balanceUsd":{"type":"number","example":48.5},"smsCredits":{"type":"integer","example":1616},"organization":{"type":"string","example":"Boutique Kinshasa SARL"}}}}}},"401":{"description":"Non autorisé","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Erreur serveur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/templates":{"get":{"tags":["Templates"],"summary":"Lister les templates","description":"Retourne tous les templates de messages de l'organisation.","security":[{"apiKey":[]}],"responses":{"200":{"description":"Liste des templates","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"templates":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"content":{"type":"string"},"category":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}}}}}}}},"401":{"description":"Non autorisé","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Erreur serveur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["Templates"],"summary":"Créer un template","description":"Crée un nouveau template de message réutilisable. Supporte les variables {prenom}, {nom}, {ville}.","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","content"],"properties":{"name":{"type":"string","example":"Promo Flash"},"content":{"type":"string","example":"Bonjour {prenom}, profitez de -30% ce weekend!"},"category":{"type":"string","example":"MARKETING"}}}}}},"responses":{"200":{"description":"Template créé","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"template":{"type":"object"}}}}}},"401":{"description":"Non autorisé","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Erreur serveur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/links":{"get":{"tags":["Liens Courts"],"summary":"Lister les liens courts","description":"Retourne tous les liens courts ujm.be créés par l'organisation avec leurs statistiques de clics.","security":[{"apiKey":[]}],"responses":{"200":{"description":"Liste des liens courts","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"links":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"shortUrl":{"type":"string"},"destinationUrl":{"type":"string"},"clicks":{"type":"integer"},"createdAt":{"type":"string","format":"date-time"}}}}}}}}},"401":{"description":"Non autorisé","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Erreur serveur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["Liens Courts"],"summary":"Créer un lien court","description":"Génère un lien court ujm.be avec tracking des clics. Idéal pour les campagnes SMS WhatsApp.","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["destinationUrl"],"properties":{"destinationUrl":{"type":"string","description":"URL de destination","example":"https://wa.me/243810000000?text=Bonjour"},"slug":{"type":"string","description":"Identifiant personnalisé (généré automatiquement si absent)","example":"wa-promo-aout"}}}}}},"responses":{"200":{"description":"Lien court créé","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"link":{"type":"object","properties":{"slug":{"type":"string"},"shortUrl":{"type":"string","example":"https://ujm.be/wa-promo-aout"},"destinationUrl":{"type":"string"}}}}}}}},"401":{"description":"Non autorisé","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Erreur serveur","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"tags":[{"name":"SMS","description":"Envoi de SMS individuels et consultation de l'historique"},{"name":"Campagnes","description":"Campagnes SMS de masse avec ciblage et planification"},{"name":"Contacts","description":"Gestion du carnet d'adresses et des groupes"},{"name":"Portefeuille","description":"Solde, recharges et transactions"},{"name":"Templates","description":"Messages pré-rédigés réutilisables"},{"name":"Liens Courts","description":"URLs ujm.be avec tracking de clics"}]}