Contrat API - Portail Technicien (Expert Hub)
1. Soldes & Crédits
GET /api/v1/resellers/credits/balance
Authentification : partner_token ou Bearer (Session Supabase)
Retourne le solde du portefeuille B2B (en XOF) et les avantages du palier.
Réponse :
{
"success": true,
"balance_fcfa": 250000,
"discount_percentage": 15,
"reseller_tier": "GOLD",
"currency": "XOF"
}
2. Génération de Licence
POST /api/v1/resellers/licenses/generate Génère une licence à partir du solde prépayé. Body :
{
"product_id": "tiketmomo_pro",
"duration_months": 12,
"quantity": 1,
"assign_to_email": "client.hotel@gmail.com",
"client_phone": "+237690000000",
"use_credit_balance": true
}
Réponse 201 :
{
"success": true,
"license": {
"id": "lic_tm_893201",
"key": "TM-PRO-2026-...",
"product_id": "tiketmomo_pro",
"duration_months": 12,
"retail_price": 50000,
"discount_applied": 15,
"final_price": 42500,
"assigned_to": "client.hotel@gmail.com",
"expires_at": "2027-10-09T00:00:00Z"
},
"remaining_credits": 207500
}
Erreurs courantes :
400 USE_PAYMENT_LINK:use_credit_balanceest faux.402 WALLET_SOLDE_INSUFFISANT: Solde insuffisant.400 INVALID_PLAN: Le plan n’existe pas.
3. Activation de Licence
POST /api/v1/resellers/licenses/activate-for-client Active une clé depuis le stock. Body :
{
"license_key": "...",
"target_client_email": "..."
}
4. Santé de la Flotte
GET /api/v1/resellers/fleet/health Récupère les statuts réseau des équipements affectés aux clients rattachés au technicien. Réponse :
{
"success": true,
"metrics": {
"total_clients": 24,
"health_score": 96,
"tiketmomo": { "active_total": 16, "online_count": 15, "offline_count": 1 },
"vpn": { "active_total": 8, "online_count": 8, "offline_count": 0 }
},
"routers": [
{
"id": "rtr_01",
"name": "Hotspot Hôtel Akwa",
"type": "TIKETMOMO",
"nas_id": "hotspot-akwa",
"status": "ONLINE",
"source": "DATAPLANE",
"last_activity_seconds": 15
}
],
"vpn_tunnels": [
{
"id": "vpn_01",
"client_ref": "hotspot-akwa",
"nas_id": "hotspot-akwa",
"latency_ms": null,
"status": "ONLINE",
"source": "DATAPLANE",
"last_activity_seconds": 45
}
]
}
5. Parrainage
GET /api/v1/referral/me Infos de parrainage enrichies. Réponse :
{
"success": true,
"promo_code": "EXPERT-2026",
"discount_offered_to_client": "10%",
"markup_percentage": 20,
"commission_rate": "10%",
"total_referrals": 14,
"active_referrals": 11,
"total_earnings": 45000,
"conversion_rate": null,
"referrals_list": [
{ "client_name": "Jean M.", "date": "2026-10-01", "status": "SUBSCRIBED", "commission_fcfa": 0 }
],
"data": { ... }
}
PUT /api/v1/referral/markup
Authentification utilisateur (Authorization: Bearer <JWT>), réservée au compte lié à son
propre profil de parrainage.
Body : {"markup_percentage": 20}. Le taux doit être compris entre 0 et 100.
La réponse rend reseller_id, promo_code, markup_percentage et updated_at.
Le portail revendeur approuvé expose aussi l’alias PUT /api/v1/resellers/store/markup avec
son authentification partner_token.
Le catalogue accepte GET /api/store/catalog?ref=<promo_code>&markup=<taux> ; le taux dans
l’URL peut être inférieur ou égal au taux enregistré, jamais supérieur.
Les commissions affichées incluent la commission habituelle sur le prix avant markup et le surplus markup crédité intégralement après confirmation de paiement.
6. Accès Technique
GET /api/v1/technique/access
Ajout de reseller_discount.
7. Recherche Client
POST /api/v1/technique/search-client
Body: {"query":"email@example.com"}
Renvoyé si la recherche par téléphone est tentée :
400 TECHNIQUE_EMAIL_REQUIRED : “La recherche par téléphone n’est pas supportée…”
8. Liste des Clients (CRM)
GET /api/v1/resellers/clients Retourne la liste paginée des clients du revendeur, enrichie avec leurs statuts (VPN, TiketMOMO, RADIUS). Réponse :
{
"success": true,
"clients": [
{
"id": "client_uuid",
"name": "Jean Dupont",
"email": "jean@example.com",
"phone": "+237...",
"status": "ACTIVE",
"active_licenses": 2,
"created_at": "...",
"affiliated_at": "...",
"affiliation_status": "ACTIVE",
"vpn": { "active": true },
"tiketmomo": { "active": true, "status": "ONLINE" },
"radius": { "active": false, "active_sessions": null, "status": "OFFLINE" },
"routers": [
{
"vpn": {
"active": true,
"public_host": "vpn.mikhmoai.com",
"ports": { "winbox": 8291, "webfig": null, "api_native": 8728, "ssh": 2222 }
},
"tiketmomo": {
"active": true,
"router_model": "RB750Gr3",
"tickets_today": 12,
"status": "ONLINE",
"last_activity_seconds": 120,
"active_sessions": 3
}
}
]
}
],
"pagination": { "page": 1, "limit": 50, "total": 1, "has_more": false }
}