Sommaire

Documentation API v1.0

API REST utilisée par les applications clientes (mobile et web) de Lebjaoui Telecom pour l'inscription, le catalogue produits, les commandes et les notifications. Toutes les routes ci-dessous répondent en JSON.

URL de base
https://lebjaoui.com/api/v1
Format
Requêtes et réponses en application/json

Enveloppe de réponse

Chaque réponse, succès ou erreur, respecte exactement la même structure :

JSON
{
  "success": true,       // true en cas de succès, false sinon
  "data": { ... },     // contenu utile (objet, tableau ou null)
  "message": "...",  // message lisible (toujours en français)
  "errors": null      // objet {champ: [messages]} en cas d'erreur de validation, null sinon
}

Authentification

Les routes protégées attendent un jeton Sanctum obtenu via /auth/login ou /auth/verify-email, envoyé dans l'en-tête suivant :

Authorization: Bearer <token>

Le jeton reste valide jusqu'à un appel explicite à /auth/logout.

Limites de débit

  • 60 requêtes / minute par adresse IP sur l'ensemble de l'API.
  • 100 requêtes / minute supplémentaires par utilisateur sur les routes authentifiées.
  • Un dépassement renvoie le code HTTP 429.

Authentification

POST /auth/register Public

Inscription d'un client

Crée un compte et envoie un code de vérification à 6 chiffres par email (valable 10 minutes). Le compte reste inutilisable jusqu'à vérification via /auth/verify-email.

ChampTypeRèglesDescription
nom_prenomstringrequis, max 100Nom complet du client
emailemailrequis, max 50Doit être unique parmi les comptes déjà vérifiés
passwordstringrequis, min 8Mot de passe
telephonestringrequis, max 50
adressestringoptionnel, max 100
id_wilayaintegeroptionnelVoir /wilayas
id_communeintegeroptionnelVoir /communes/{wilaya}
cURL
curl -X POST https://lebjaoui.com/api/v1/auth/register \
  -H "Content-Type: application/json" \
  -d '{
    "nom_prenom": "Karim Benali",
    "email": "karim@example.com",
    "password": "MotDePasse123",
    "telephone": "0555112233",
    "adresse": "12 rue des Frères, Alger",
    "id_wilaya": 16,
    "id_commune": 1601
  }'
Réponse 200
{
  "success": true,
  "data": {
    "verification_required": true,
    "email": "karim@example.com",
    "expires_in_minutes": 10
  },
  "message": "Code envoyé. Vérifiez votre email.",
  "errors": null
}

Erreur 422 si l'email est déjà utilisé par un compte vérifié ou par un client abonné (synchronisé depuis le point de vente).

POST /auth/verify-email Public

Vérification de l'email

Valide le code reçu par email et renvoie directement un jeton de session (l'utilisateur est connecté après vérification).

ChampTypeRègles
emailemailrequis, max 255
codestringrequis, 6 caractères
Réponse 200
{
  "success": true,
  "data": {
    "token": "1|xLk9...(jeton Sanctum)",
    "client": {
      "id": 42,
      "nom_prenom": "Karim Benali",
      "email": "karim@example.com",
      "telephone": "0555112233",
      "type_client": "simple",
      "tarif": 1
    }
  },
  "message": "Email vérifié",
  "errors": null
}

Erreurs possibles : 404 (email inconnu), 422 (code invalide, expiré ou incorrect).

POST /auth/resend-email-code Public

Renvoyer le code de vérification

À utiliser si le code initial a expiré (10 minutes) ou n'a pas été reçu.

ChampTypeRègles
emailemailrequis, max 255
Réponse 200
{ "success": true, "data": { "verification_required": true, "email": "karim@example.com", "expires_in_minutes": 10 }, "message": "Code renvoyé", "errors": null }
POST /auth/login Public

Connexion

ChampTypeRègles
emailemailrequis
passwordstringrequis
cURL
curl -X POST https://lebjaoui.com/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"karim@example.com","password":"MotDePasse123"}'
Réponse 200
{
  "success": true,
  "data": {
    "token": "1|xLk9...(jeton Sanctum)",
    "client": {
      "id": 42,
      "nom_prenom": "Karim Benali",
      "email": "karim@example.com",
      "telephone": "0555112233",
      "adresse": "12 rue des Frères, Alger",
      "id_wilaya": 16,
      "id_commune": 1601,
      "type_client": "simple",
      "tarif": 1
    }
  },
  "message": "Connexion réussie",
  "errors": null
}

Erreurs : 401 (identifiants invalides), 403 (compte désactivé ou email non vérifié). type_client vaut abonne pour un client synchronisé depuis le point de vente (accès aux produits réservés et à sa grille tarifaire), sinon simple.

POST /auth/logout Authentification requise

Déconnexion

Révoque le jeton d'accès utilisé pour cet appel.

cURL
curl -X POST https://lebjaoui.com/api/v1/auth/logout \
  -H "Authorization: Bearer <token>"
GET /auth/me Authentification requise

Profil du client connecté

Réponse 200
{
  "success": true,
  "data": {
    "id": 42,
    "nom_prenom": "Karim Benali",
    "email": "karim@example.com",
    "telephone": "0555112233",
    "adresse": "12 rue des Frères, Alger",
    "id_wilaya": 16,
    "id_commune": 1601,
    "type_client": "simple",
    "tarif": 1
  },
  "message": "Profil",
  "errors": null
}
PUT /auth/profil Authentification requise

Modifier le profil

ChampTypeRègles
nom_prenomstringrequis, max 100
telephonestringoptionnel, max 50
adressestringrequis, max 100
id_wilayaintegerrequis
id_communeintegerrequis
Réponse 200
{
  "success": true,
  "data": {
    "id": 42,
    "nom_prenom": "Karim Benali",
    "telephone": "0555112233",
    "adresse": "12 rue des Frères, Alger",
    "id_wilaya": 16,
    "id_commune": 1601
  },
  "message": "Profil mis à jour",
  "errors": null
}
PUT /auth/password Authentification requise

Changer le mot de passe

ChampTypeRègles
current_passwordstringrequis
passwordstringrequis, min 8, confirmé
password_confirmationstringrequis, identique à password

Réponse : data: null, message: "Mot de passe mis à jour". Erreur 422 si current_password est incorrect.

Produits

L'authentification est optionnelle sur ce groupe : un jeton valide, s'il est fourni, débloque l'accès aux produits réservés aux abonnés et applique la grille tarifaire du client.

GET /produits Authentification optionnelle

Liste des produits

Paramètre (query)TypeDescription
id_categorieintegerFiltre par catégorie
searchstringRecherche sur la désignation ou la référence
pageintegerPagination, 20 produits par page
cURL
curl "https://lebjaoui.com/api/v1/produits?search=telephone&page=1" \
  -H "Authorization: Bearer <token>"   # optionnel
Réponse 200 (extrait)
{
  "data": {
    "items": [{
      "id": 101,
      "reference": "REF-101",
      "designation": "Câble USB-C 1m",
      "description": "...",
      "pv_1": 890, "pv_2": 850, "pv_3": 800,
      "tva": null,
      "promo_enabled": true,
      "promo_start_at": "2026-09-01T00:00:00+01:00",
      "promo_end_at": "2026-09-30T23:59:59+01:00",
      "promo_quantity": null,
      "promo_price": 750,
      "promo_active_now": true,
      "prix_standard": 890,
      "prix": 750,
      "stock": 34,
      "image_principale": "https://.../storage/produits/101.webp",
      "categorie": "Accessoires",
      "abonne_only": 0,
      "enable_tier_pricing": false,
      "quantity_prices": [],
      "actif": 1,
      "images": [{ "id": 5, "filename": "101_1.webp", "url_principale": "...", "url_thumbnail": "...", "ordre": 0 }]
    }],
    "pagination": { "current_page": 1, "last_page": 6, "per_page": 20, "total": 112 }
  }
}

`prix` est le prix unitaire réellement applicable pour ce client (tarif abonné et promotion déjà pris en compte) ; `prix_standard` est le prix affiché barré. `quantity_prices` liste les paliers de prix par quantité quand `enable_tier_pricing` est vrai.

GET /produits/{id} Authentification optionnelle

Détail d'un produit

Renvoie les mêmes champs qu'un élément de la liste. 404 si le produit n'existe pas, est inactif, ou est réservé aux abonnés et que l'appelant n'est pas un client abonné.

cURL
curl https://lebjaoui.com/api/v1/produits/101
GET /produits/categories Authentification optionnelle

Liste des catégories

Réponse 200
{ "success": true, "data": ["Accessoires", "Téléphonie", "Informatique"], "message": "Catégories", "errors": null }

Commandes

POST /commandes Authentification requise

Créer une commande

ChampTypeRèglesDescription
adresse_livraisonstringrequis
id_wilayaintegerrequisDoit exister dans /wilayas
id_communeintegerrequisDoit exister dans /communes/{wilaya}
notesstringoptionnel
panierarrayrequis, min 1 ligne
panier[].id_produitintegerrequisDoit exister dans produit.id
panier[].quantiteintegerrequis, min 1
cURL
curl -X POST https://lebjaoui.com/api/v1/commandes \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "adresse_livraison": "12 rue des Frères, Alger",
    "id_wilaya": 16,
    "id_commune": 1601,
    "notes": "Livrer après 17h",
    "panier": [
      { "id_produit": 101, "quantite": 2 },
      { "id_produit": 205, "quantite": 1 }
    ]
  }'
Réponse 201
{
  "success": true,
  "data": {
    "commande": {
      "id": 7841,
      "id_client": 42,
      "date_cmd": "2026-09-12 10:32:00",
      "statut": "en_attente",
      "montant_total": 2080,
      "sous_total": 1780,
      "frais_livraison": 300,
      "adresse_livraison": "12 rue des Frères, Alger",
      "id_wilaya": 16,
      "id_commune": 1601,
      "notes": "Livrer après 17h",
      "synced_pme": 0
    },
    "lignes": [
      { "id_produit": 101, "quantite": 2, "prix_unitaire": 890, "sous_total": 1780, "produit_designation": "Câble USB-C 1m" }
    ]
  },
  "message": "Commande créée",
  "errors": null
}

Erreur 400 (message explicite) si un produit est introuvable, réservé aux abonnés, ou en stock insuffisant — toute la commande est alors annulée (transaction).

GET /commandes Authentification requise

Mes commandes

Liste paginée (20/page) des commandes du client connecté, triée du plus récent au plus ancien.

Réponse 200 (extrait)
{ "data": { "items": [{ "id": 7841, "date_cmd": "2026-09-12 10:32:00", "statut": "en_attente", "montant_total": 2080, "sous_total": 1780, "frais_livraison": 300, "adresse_livraison": "...", "synced_pme": 0 }], "pagination": { "current_page": 1, "last_page": 2, "per_page": 20, "total": 23 } } }
GET /commandes/{id} Authentification requise

Détail d'une commande

404 si la commande n'existe pas ou n'appartient pas au client connecté.

Valeurs possibles de `statut`
en_attente validee en_preparation expediee livree annulee archivee
Réponse 200 (extrait)
{ "data": { "commande": { "id": 7841, "date_cmd": "...", "statut": "en_preparation", "montant_total": 2080, "...": "..." }, "lignes": [{ "id_produit": 101, "quantite": 2, "prix_unitaire": 890, "sous_total": 1780, "produit_designation": "...", "produit_reference": "...", "produit_image": "..." }] } }

Notifications

GET /notifications Authentification requise

Liste des notifications

Les 50 dernières notifications du client connecté (changement de statut de commande, etc.), triées de la plus récente à la plus ancienne.

Réponse 200
{ "data": { "non_lues": 2, "notifications": [{ "id": "9c1e...-uuid", "type": "App\\Notifications\\StatutCommandeChange", "data": { "...":"..." }, "read_at": null, "created_at": "2026-09-12T09:00:00.000000Z" }] } }
PUT /notifications/{id}/lu Authentification requise

Marquer une notification comme lue

`id` est l'UUID de la notification (voir `notifications[].id` ci-dessus). 404 si elle n'existe pas ou n'appartient pas au client.

PUT /notifications/tout-lire Authentification requise

Tout marquer comme lu

DELETE /notifications/{id} Authentification requise

Supprimer une notification

Notifications push (FCM)

POST /fcm/token Authentification requise

Enregistrer un token Firebase Cloud Messaging

À appeler à chaque démarrage de l'application mobile pour permettre l'envoi de notifications push. Un même client peut avoir un token actif par type d'appareil (`android`, `ios`) ; ré-enregistrer met simplement à jour le token existant.

ChampTypeRègles
tokenstringrequis
device_typestringrequis, android ou ios

Géographie

Référentiel des 58 wilayas et communes d'Algérie, mis en cache serveur 15 minutes.

GET /wilayas Public

Liste des wilayas

Réponse 200 (extrait)
{ "data": [{ "ID_WILAYA": 16, "WILAYA": "ALGER (16)", "WILAYA2": "16 - ALGER", "WILAYA_AR": "الجزائر", "WILAYA_AR2": "16 - الجزائر" }] }
GET /communes/{wilaya} Public

Communes d'une wilaya

`{wilaya}` est l'`ID_WILAYA` obtenu via /wilayas. Résultat trié par ordre alphabétique.

Réponse 200 (extrait)
curl https://lebjaoui.com/api/v1/communes/16

{ "data": [{ "ID_COMMUNE": 1601, "COMMUNE": "Alger Centre", "COMMUNE_AR": "الجزائر الوسطى", "ID_WILAYA": 16 }] }

Codes d'erreur

CodeSignification
200Succès
201Ressource créée (commande)
400Règle métier non respectée (stock, produit réservé, etc.) — voir `message`
401Non authentifié : jeton absent, invalide ou identifiants incorrects
403Action interdite : compte désactivé, email non vérifié, ressource non autorisée
404Ressource introuvable
422Échec de validation — `errors` contient le détail par champ, ou règle métier (mot de passe actuel incorrect, code de vérification invalide, etc.)
429Trop de requêtes — voir Limites de débit
500Erreur serveur inattendue
Exemple — 422 de validation
{
  "success": false,
  "data": null,
  "message": "Validation échouée",
  "errors": {
    "email": ["Le champ email doit être une adresse email valide."]
  }
}