KOPA Distribution
Navigation

La distribution intelligente des rafraîchissants

Documentation API KOPA

Référence complète de tous les endpoints disponibles.

Base URL https://kopa.harcrosoft-it.com/api/v2.1.0

Authentification

Toutes les routes protégées nécessitent un header Authorization: Bearer {token} obtenu via POST /api/v2.1.0/auth/login.

Méthodes HTTP

GET POST PATCH DELETE

Health

GET /api/v2.1.0/health Public

Vérifie l'état du serveur et de la base de données.

Réponse 200

{
    "status": "ok",
    "database": "connected",
    "timestamp": "2026-01-15T10:30:00Z"
}

Rôles & permissions

Le rôle est une colonne role de la table users, vérifiée par le middleware role:{rôle},{rôle} sur chaque groupe de routes. Il est fixé à la création et modifiable uniquement par un super_admin via PATCH /admin/users/{id}.

Rôle Portail Routes accessibles
super_admin/bo/admin/admin/*
support/bo/support/support/* (staff)
producteur/bo/producteur/producteur/*
micro_centre/bo/microcentre/microcentre/*
livreur/bo/livreur/livreur/*
client/app/client/* (toutes les permissions employé sont bypassées)
client_secondaire/app/client/* (uniquement ses permissions accordées)
consommateur/app/achat-express/consommateur/*, /support/*, /paiements/*

Toutes les routes authentifiées passent aussi par le middleware active : un compte désactivé reçoit 403 ACCOUNT_DISABLED, un compte non vérifié 403 ACCOUNT_UNVERIFIED.

Permissions employé (client_secondaire)

Stockées dans la table employe_permissions et vérifiées par le middleware permission:{permission}. Le rôle client (owner) les bypass toutes ; tout autre rôle reçoit un 403.

view_catalogue create_commande view_commandes modify_commandes view_historique view_stats

Gérées par le owner via POST /client/employes et PATCH /client/employes/{id}/permissions (au minimum 1 permission). Les commandes et la fidélité sont rattachées au compte owner : un employé et son owner partagent le même périmètre de données.

Authentification

POST /api/v2.1.0/auth/register Public

Inscription d'un nouvel utilisateur. Envoie un OTP par SMS pour vérification du téléphone.

Request Body

{
    "phone": "+2250708091011",
    "nom": "Kouassi",
    "prenom": "Jean",
    "email": "jean@example.com",
    "password": "secret123",
    "role": "client"
}

Champs requis : phone (format +242…), password (min 8), nom. role optionnel : client (défaut) ou consommateur uniquement.

Réponse 201

{
    "message": "Inscription réussie. Un code de vérification a été envoyé par SMS.",
    "user": { "id": "uuid", "phone": "+24206123456", "role": "client", "verified": false }
}
POST /api/v2.1.0/auth/verify-phone Public

Vérifie le code OTP reçu par SMS et active le compte.

Request Body

{
    "phone": "+2250708091011",
    "code": "123456"
}

Réponse 200

{
    "message": "Téléphone vérifié",
    "token": "1|abcDEFghiJKLmnoPQRstuvwxyz..."
}
POST /api/v2.1.0/auth/resend-otp Public

Renvoie un nouveau code OTP par SMS.

Request Body

{
    "phone": "+2250708091011"
}

Réponse 200

{
    "message": "OTP renvoyé"
}
POST /api/v2.1.0/auth/login Public

Connexion. Retourne un token Sanctum si les identifiants sont valides et le téléphone vérifié.

Request Body

{
    "phone": "+2250708091011",
    "password": "secret123"
}

Réponse 200

{
    "message": "Connexion réussie",
    "token": "1|abcDEFghiJKLmnoPQRstuvwxyz...",
    "user": { "id": 1, "nom": "Kouassi", "prenom": "Jean", "role": "client" }
}
POST /api/v2.1.0/auth/logout Auth

Révoque le token d'authentification actuel.

Réponse 200

{
    "message": "Déconnecté"
}

Consommateur

POST /api/v2.1.0/consommateur/achat-express Auth

Achat express — permet au consommateur final de commander directement via QR code produit.

Request Body

{
    "qr_code": "KOPA-PRD-ABC123",
    "quantite": 5,
    "mode_paiement": "mobile_money"
}

Réponse 201

{
    "message": "Commande créée",
    "commande": { "id": 42, "montant_total": 7500, "statut": "en_attente" }
}

Webhooks

POST /api/v2.1.0/webhooks/paiement/{provider} Public

Webhook de callback pour les fournisseurs de paiement (Orange Money, MTN MoMo, Wave, etc.). Le provider est validé via une signature HMAC.

Paramètres

ParamTypeDescription
providerstringNom du provider (orange_money, mtn_momo, wave)

Request Body (exemple Orange Money)

{
    "status": "SUCCESS",
    "transaction_id": "OM-20260115-001",
    "amount": 15000,
    "external_id": "CMD-42"
}

Réponse 200

{
    "received": true
}

Admin super_admin

GET /api/v2.1.0/admin/dashboard super_admin

Tableau de bord admin avec KPIs globaux.

Réponse 200

{
    "total_users": 1247,
    "total_producteurs": 89,
    "total_microcentres": 156,
    "total_commandes": 3420,
    "chiffre_affaires": 45600000,
    "commandes_en_cours": 47,
    "nouveaux_utilisateurs_ce_mois": 34
}
POST /api/v2.1.0/admin/users/producteur super_admin

Crée un compte producteur.

Request Body

{
    "nom": "Aka",
    "prenom": "Moussa",
    "phone": "+2250708091012",
    "email": "moussa@farm.ci",
    "password": "secure456",
    "localisation": "Yamoussoukro",
    "description": "Producteur de manioc"
}

Réponse 201

{
    "message": "Producteur créé",
    "user": { "id": 101, "nom": "Aka", "prenom": "Moussa", "role": "producteur" }
}
POST /api/v2.1.0/admin/users/microcentre super_admin

Crée un compte micro-centre.

Request Body

{
    "nom": "Boutique Aya",
    "prenom": "Fatou",
    "phone": "+2250506070809",
    "email": "aya@boutique.ci",
    "password": "secure789",
    "localisation": "Abobo, Abidjan",
    "description": "Micro-centre alimentaire"
}
GET /api/v2.1.0/admin/users super_admin

Liste paginée de tous les utilisateurs. Filtres optionnels : role, search, active.

Query Parameters

?role=producteur&search=Kouassi&active=1&page=1&per_page=20

Réponse 200

{
    "data": [
        { "id": "uuid", "nom": "Kouassi", "prenom": "Jean", "phone": "+24206123456", "role": "client", "active": true, "verified": true }
    ],
    "links": { "first": "...", "last": "...", "prev": null, "next": "..." },
    "meta": { "current_page": 1, "last_page": 62, "per_page": 20, "total": 1247 }
}
PATCH /api/v2.1.0/admin/users/{id} super_admin

Modifie un utilisateur. Champs acceptés : nom, active, verified, role. Le changement de rôle n'est pas possible sur son propre compte, et le passage hors de client_secondaire supprime le lien employé et ses permissions.

Request Body

{
    "nom": "Kouassi",
    "active": false,
    "role": "producteur"
}
DELETE /api/v2.1.0/admin/users/{id} super_admin

Supprime un utilisateur.

Réponse 200

{
    "message": "Utilisateur supprimé"
}
GET /api/v2.1.0/admin/commandes super_admin

Liste paginée de toutes les commandes. Filtres : statut, date_debut, date_fin.

Réponse 200

{
    "data": [
        {
            "id": 42,
            "client": { "id": 1, "nom": "Kouassi", "prenom": "Jean" },
            "micro_centre": { "id": 5, "nom": "Boutique Aya" },
            "montant_total": 15000,
            "statut": "en_attente",
            "paiement_statut": "en_attente",
            "created_at": "2026-01-15T10:30:00Z"
        }
    ],
    "meta": { "current_page": 1, "last_page": 171, "per_page": 20, "total": 3420 }
}
GET /api/v2.1.0/admin/commandes/{id} super_admin

Détail complet d'une commande.

Réponse 200

{
    "id": 42,
    "client": { "id": 1, "nom": "Kouassi", "prenom": "Jean", "phone": "+2250708091011" },
    "micro_centre": { "id": 5, "nom": "Boutique Aya" },
    "items": [
        { "produit": { "nom": "Manioc", "unite": "kg" }, "quantite": 10, "prix_unitaire": 1500 }
    ],
    "montant_total": 15000,
    "statut": "en_attente",
    "pin": "1234",
    "paiement": { "statut": "en_attente", "provider": "orange_money" },
    "livraison": null,
    "created_at": "2026-01-15T10:30:00Z"
}
PATCH /api/v2.1.0/admin/commandes/{id}/forcer-statut super_admin

Force le statut d'une commande (admin override).

Request Body

{
    "statut": "livree",
    "motif": "Confirmation téléphonique du client"
}
PATCH /api/v2.1.0/admin/commandes/{id}/debloquer-pin super_admin

Débloque le PIN de réception d'une commande (en cas de oubli/erreur).

Réponse 200

{
    "message": "PIN débloqué",
    "pin": "1234"
}
GET /api/v2.1.0/admin/rapports/{type} super_admin

Génère un rapport. Types : ventes, performances, stocks, satisfaction, delais.

Query Parameters

?periode_debut=2026-01-01&periode_fin=2026-01-31

Réponse 200

{
    "type": "ventes",
    "periode": { "debut": "2026-01-01", "fin": "2026-01-31" },
    "total_ventes": 342,
    "chiffre_affaires": 45600000,
    "top_produits": [ ... ],
    "evolution_quotidienne": [ ... ]
}

Client client

GET /api/v2.1.0/client/dashboard client

Réponse 200

{
    "total_commandes": 24,
    "commandes_en_cours": 3,
    "montant_total_depense": 360000,
    "points_fidelite": 1200,
    "derniere_commande": { "id": 42, "statut": "en_transit", "montant_total": 15000 }
}
GET /api/v2.1.0/client/catalogue client

Catalogue des produits disponibles. Filtres : categorie, search, microcentre_id.

Réponse 200

{
    "data": [
        {
            "id": 10,
            "nom": "Manioc premium",
            "categorie": "tubercules",
            "prix_unitaire": 1500,
            "unite": "kg",
            "stock_disponible": 250,
            "producteur": { "id": 101, "nom": "Aka Moussa" },
            "micro_centre": { "id": 5, "nom": "Boutique Aya" },
            "promotion": { "remise_pct": 10, "prix_remise": 1350 }
        }
    ],
    "meta": { "current_page": 1, "last_page": 5, "total": 98 }
}
POST /api/v2.1.0/client/commandes client

Crée une nouvelle commande.

Request Body

{
    "micro_centre_id": 5,
    "items": [
        { "produit_id": 10, "quantite": 10 },
        { "produit_id": 12, "quantite": 5 }
    ],
    "mode_paiement": "mobile_money",
    "adresse_livraison": "Abobo PK18, Abidjan",
    "utiliser_points_fidelite": false
}

Réponse 201

{
    "message": "Commande créée",
    "commande": { "id": 43, "montant_total": 22500, "pin": "5678", "statut": "en_attente_paiement" }
}
GET /api/v2.1.0/client/commandes client

Historique des commandes du client. Filtre : statut.

Réponse 200

{
    "data": [
        { "id": 42, "montant_total": 15000, "statut": "livree", "created_at": "2026-01-10T08:00:00Z" },
        { "id": 43, "montant_total": 22500, "statut": "en_transit", "created_at": "2026-01-15T10:30:00Z" }
    ],
    "meta": { "current_page": 1, "last_page": 2, "total": 24 }
}
GET /api/v2.1.0/client/commandes/{id} client

Détail d'une commande client.

GET /api/v2.1.0/client/commandes/{id}/suivi client

Suivi en temps réel d'une commande.

Réponse 200

{
    "commande_id": 42,
    "statut": "en_transit",
    "livreur": { "nom": "Bamba", "phone": "+2250102030405" },
    "position_actuelle": { "lat": 5.3600, "lng": -4.0083 },
    "etapes": [
        { "statut": "commande_recue", "date": "2026-01-15T10:30:00Z" },
        { "statut": "paiement_confirmé", "date": "2026-01-15T10:31:00Z" },
        { "statut": "en_preparation", "date": "2026-01-15T10:35:00Z" },
        { "statut": "en_transit", "date": "2026-01-15T11:00:00Z" }
    ]
}
PATCH /api/v2.1.0/client/commandes/{id}/confirmer-reception client

Confirme la réception de la commande en entrant le PIN.

Request Body

{
    "pin": "5678"
}
GET /api/v2.1.0/client/employes client

Liste des employés du client.

Réponse 200

{
    "data": [
        { "id": 201, "nom": "Traore", "prenom": "Aminata", "phone": "+2250707060504", "permissions": ["view_catalogue", "create_commande"], "active": true }
    ]
}
POST /api/v2.1.0/client/employes client

Ajoute un employé au compte client.

Request Body

{
    "nom": "Traore",
    "prenom": "Aminata",
    "phone": "+2250707060504",
    "email": "aminata@boutique.ci",
    "password": "emp123456",
    "permissions": ["view_catalogue", "create_commande"]
}
PATCH /api/v2.1.0/client/employes/{id}/permissions client

Request Body

{
    "permissions": ["view_catalogue", "create_commande", "view_commandes", "view_historique"]
}
PATCH /api/v2.1.0/client/employes/{id}/desactiver client

Désactive le compte d'un employé.

PATCH /api/v2.1.0/client/employes/{id}/reactiver client

Réactive le compte d'un employé.

GET /api/v2.1.0/client/historique client

Historique complet des transactions et interactions.

GET /api/v2.1.0/client/fidelite client

Réponse 200

{
    "points_disponibles": 1200,
    "points_utilises": 800,
    "historique": [
        { "type": "gain", "points": 150, "description": "Commande #42", "date": "2026-01-10T08:00:00Z" },
        { "type": "utilisation", "points": -200, "description": "Réduction appliquée", "date": "2026-01-12T14:00:00Z" }
    ]
}
POST /api/v2.1.0/client/fidelite/utiliser client

Utilise des points de fidélité sur une commande.

Request Body

{
    "commande_id": 43,
    "points": 500
}

Producteur producteur

GET /api/v2.1.0/producteur/dashboard producteur

Réponse 200

{
    "total_produits": 12,
    "total_ventes_mois": 245,
    "chiffre_affaires_mois": 6780000,
    "produits_alerte_stock": 3,
    "derniere_commande": { "id": 42, "produit": "Manioc", "quantite": 100 }
}
GET /api/v2.1.0/producteur/produits producteur

Réponse 200

{
    "data": [
        { "id": 10, "nom": "Manioc premium", "categorie": "tubercules", "prix_unitaire": 1500, "unite": "kg", "stock": 250, "is_disponible": true, "qr_code": "KOPA-PRD-ABC123" }
    ]
}
POST /api/v2.1.0/producteur/produits producteur

Request Body

{
    "nom": "Manioc premium",
    "description": "Manioc de qualité supérieure, récolte fraîche",
    "categorie": "tubercules",
    "prix_unitaire": 1500,
    "unite": "kg",
    "stock": 250,
    "seuil_alerte": 20
}
PATCH /api/v2.1.0/producteur/produits/{id} producteur

Modifie un produit existant.

Request Body

{
    "prix_unitaire": 1800,
    "is_disponible": false
}
DELETE /api/v2.1.0/producteur/produits/{id} producteur

Supprime un produit.

GET /api/v2.1.0/producteur/stats producteur

Statistiques détaillées du producteur.

Réponse 200

{
    "ventes_par_mois": [ { "mois": "2026-01", "total": 245, "chiffre_affaires": 6780000 } ],
    "produits_plus_vendus": [ { "nom": "Manioc", "vendus": 120 } ],
    "taux_rupture_stock": 8.5,
    "nombre_microcentres_partenaires": 12
}
GET /api/v2.1.0/producteur/tracabilite/{qr_code} producteur

Retourne la chaîne de traçabilité complète d'un produit via son QR code.

Réponse 200

{
    "qr_code": "KOPA-PRD-ABC123",
    "produit": { "nom": "Manioc premium", "categorie": "tubercules" },
    "producteur": { "nom": "Aka Moussa", "localisation": "Yamoussoukro" },
    "date_recolte": "2026-01-10",
    "micro_centres": [
        { "nom": "Boutique Aya", "date_reception": "2026-01-11", "quantite": 100 }
    ],
    "derniere_mise_a_jour": "2026-01-15T10:30:00Z"
}
GET /api/v2.1.0/producteur/alertes producteur

Alertes de stock bas et commandes en attente.

Réponse 200

{
    "stock_bas": [
        { "produit_id": 10, "nom": "Manioc", "stock_actuel": 15, "seuil": 20 }
    ],
    "commandes_en_attente": 3
}
GET /api/v2.1.0/producteur/promotions producteur

Réponse 200

{
    "data": [
        { "id": 1, "produit": { "nom": "Manioc" }, "remise_pct": 10, "date_debut": "2026-01-15", "date_fin": "2026-01-31", "active": true }
    ]
}
POST /api/v2.1.0/producteur/promotions producteur

Request Body

{
    "produit_id": 10,
    "remise_pct": 10,
    "date_debut": "2026-01-15",
    "date_fin": "2026-01-31"
}
DELETE /api/v2.1.0/producteur/promotions/{id} producteur

Supprime une promotion.

MicroCentre micro_centre

GET /api/v2.1.0/microcentre/stock micro_centre

Réponse 200

{
    "data": [
        { "id": 5, "produit": { "id": 10, "nom": "Manioc" }, "quantite": 200, "seuil_alerte": 20, "statut": "ok" }
    ],
    "alertes_stock": 2
}
POST /api/v2.1.0/microcentre/stock/ajuster micro_centre

Ajuste le stock d'un produit (+entrée ou -sortie).

Request Body

{
    "produit_id": 10,
    "quantite": 50,
    "type": "entree",
    "motif": "Réception depuis producteur"
}
PATCH /api/v2.1.0/microcentre/stock/{id}/seuil micro_centre

Modifie le seuil d'alerte d'un stock.

Request Body

{
    "seuil_alerte": 30
}
GET /api/v2.1.0/microcentre/stock/historique micro_centre

Historique des mouvements de stock.

Réponse 200

{
    "data": [
        { "produit": "Manioc", "type": "entree", "quantite": 50, "date": "2026-01-15T08:00:00Z", "motif": "Réception producteur" },
        { "produit": "Manioc", "type": "sortie", "quantite": 10, "date": "2026-01-15T14:00:00Z", "motif": "Commande #42" }
    ]
}
GET /api/v2.1.0/microcentre/commandes micro_centre

Commandes associées au micro-centre. Filtre : statut.

GET /api/v2.1.0/microcentre/commandes/{id} micro_centre

Détail d'une commande pour le micro-centre.

PATCH /api/v2.1.0/microcentre/commandes/{id}/confirmer micro_centre

Confirme la réception de la commande par le micro-centre.

PATCH /api/v2.1.0/microcentre/commandes/{id}/preparer micro_centre

Passe la commande en statut "en préparation".

POST /api/v2.1.0/microcentre/commandes/{id}/assigner-livreur micro_centre

Request Body

{
    "livreur_id": 301
}
PATCH /api/v2.1.0/microcentre/commandes/{id}/annuler micro_centre

Request Body

{
    "motif": "Stock insuffisant"
}
POST /api/v2.1.0/microcentre/livreurs micro_centre

Ajoute un livreur au micro-centre.

Request Body

{
    "nom": "Bamba",
    "prenom": "Ibrahim",
    "phone": "+2250102030405",
    "email": "ibrahim@livraison.ci",
    "password": "liv123456"
}
GET /api/v2.1.0/microcentre/livreurs micro_centre

Réponse 200

{
    "data": [
        { "id": "uuid", "nom": "Bamba Ibrahim", "phone": "+24206123456", "active": true, "missions_en_cours": 2 }
    ]
}
PATCH /api/v2.1.0/microcentre/livreurs/{id}/toggle micro_centre

Active/Désactive un livreur.

Livreur livreur

GET /api/v2.1.0/livreur/dashboard livreur

Réponse 200

{
    "missions_en_cours": 2,
    "missions_terminees_jour": 5,
    "missions_totales": 234,
    "taux_reussite": 97.5
}
GET /api/v2.1.0/livreur/missions livreur

Réponse 200

{
    "data": [
        {
            "id": 42,
            "client": { "nom": "Kouassi Jean", "phone": "+2250708091011" },
            "adresse": "Abobo PK18, Abidjan",
            "montant_total": 15000,
            "statut": "en_transit",
            "pin": "5678",
            "created_at": "2026-01-15T10:30:00Z"
        }
    ]
}
PATCH /api/v2.1.0/livreur/missions/{id}/livrer livreur

Marque la livraison comme effectuée. La validation finale nécessite le PIN client.

Réponse 200

{
    "message": "Livraison effectuée, en attente de validation PIN",
    "statut": "livraison_effectuee"
}
GET /api/v2.1.0/livreur/historique livreur

Historique des livraisons passées.

PATCH /api/v2.1.0/livreur/missions/{id}/valider-pin livreur

Valide la livraison avec le PIN fourni par le client.

Request Body

{
    "pin": "5678"
}

Réponse 200

{
    "message": "Livraison confirmée",
    "statut": "livree"
}

Paiements Auth

POST /api/v2.1.0/paiements/initier Auth

Initie un paiement pour une commande via mobile money.

Request Body

{
    "commande_id": 42,
    "provider": "orange_money",
    "phone": "+2250708091011",
    "montant": 15000
}

Réponse 201

{
    "message": "Paiement initié",
    "transaction_id": "TXN-20260115-001",
    "statut": "en_attente",
    "redirect_url": "https://checkout.orange.com/..."
}
GET /api/v2.1.0/paiements/{transaction_id}/statut Auth

Vérifie le statut d'une transaction.

Réponse 200

{
    "transaction_id": "TXN-20260115-001",
    "statut": "succes",
    "montant": 15000,
    "provider": "orange_money",
    "date_confirmation": "2026-01-15T10:32:00Z"
}
GET /api/v2.1.0/paiements/commande/{commande_id} Auth

Retourne les informations de paiement d'une commande.

Réponse 200

{
    "commande_id": 42,
    "transaction_id": "TXN-20260115-001",
    "montant": 15000,
    "provider": "orange_money",
    "statut": "succes"
}

Support Auth

POST /api/v2.1.0/support/tickets Auth

Crée un ticket de support.

Request Body

{
    "titre": "Commande non reçue",
    "description": "La commande #42 n'a toujours pas été livrée après 48h.",
    "type": "commande",
    "priorite": "haute",
    "commande_id": 42
}

Réponse 201

{
    "message": "Ticket créé",
    "ticket": { "id": 1, "titre": "Commande non reçue", "statut": "ouvert", "priorite": "haute" }
}
GET /api/v2.1.0/support/tickets Auth

Liste des tickets. Filtres : statut, priorite, type.

Réponse 200

{
    "data": [
        { "id": 1, "titre": "Commande non reçue", "type": "commande", "priorite": "haute", "statut": "ouvert", "created_by": { "nom": "Kouassi Jean" }, "created_at": "2026-01-15T10:30:00Z" }
    ],
    "meta": { "current_page": 1, "last_page": 1, "total": 1 }
}
GET /api/v2.1.0/support/tickets/{id} Auth

Réponse 200

{
    "id": 1,
    "titre": "Commande non reçue",
    "description": "La commande #42 n'a toujours pas été livrée après 48h.",
    "type": "commande",
    "priorite": "haute",
    "statut": "ouvert",
    "created_by": { "id": 1, "nom": "Kouassi Jean" },
    "commentaires": [
        { "id": 1, "auteur": { "nom": "Admin" }, "contenu": "Nous vérifions avec le micro-centre.", "created_at": "2026-01-15T11:00:00Z" }
    ],
    "created_at": "2026-01-15T10:30:00Z"
}
POST /api/v2.1.0/support/tickets/{id}/commentaires Auth

Request Body

{
    "contenu": "Le livreur est en route, arrivée prévue dans 30 minutes."
}
PATCH /api/v2.1.0/support/tickets/{id} Auth

Met à jour le statut ou la priorité d'un ticket.

Request Body

{
    "statut": "resolu",
    "priorite": "normale"
}
GET /api/v2.1.0/support/stats Auth

Réponse 200

{
    "total_tickets": 45,
    "ouverts": 8,
    "en_cours": 12,
    "resolus": 25,
    "temps_moyen_resolution_h": 4.2
}

KOPA API v2.1.0 — Dernière mise à jour : 06/10/2026