Documentation J+SERVICES Guides Référence API

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 :

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 }
}