Documentation et disponibilité de l'API Commercy
Consultez les endpoints, exemples et statut en temps réel des services fournisseurs & revendeurs.
Aperçu
/api/v1/, compression et CORS avancéDémarrage rapide
URL de base
https://api.commercy.net/api/v1
Authentification
// Connexion pour obtenir un token JWT
const response = await fetch('https://api.commercy.net/api/v1/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
identifier: 'user@example.com',
password: 'password'
})
});
const { token } = await response.json();
// Utiliser le token dans les requêtes suivantes
const apiResponse = await fetch('https://api.commercy.net/api/v1/orders', {
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});
Statut de l'API
Endpoints API
Supervision & santé
GET
/api/v1/health
Contrôle complet : MySQL, pool de connexions, mémoire et charge serveur. Retourne 503 si le système est critique.
{
"status": "healthy",
"message": "All systems operational",
"timestamp": "2026-06-27T12:00:00.000Z",
"apiVersion": "1",
"checks": {
"database": { "status": "healthy", "latencyMs": 4 },
"connectionPool": { "status": "healthy" },
"process": { "status": "healthy", "uptimeSeconds": 86400 }
}
}
GET
/api/v1/health/ready
Readiness probe — prêt à servir du trafic (base de données requise). Utile pour Kubernetes / load balancers.
GET
/api/v1/health/live
Liveness probe — le processus Node.js répond. Ne vérifie pas MySQL.
Tableau de bord visuel : /system-health · Détails complets avec ?token= ou en-tête X-Health-Token si HEALTH_DETAIL_TOKEN est configuré.
/api/v1/health
Contrôle complet : MySQL, pool de connexions, mémoire et charge serveur. Retourne 503 si le système est critique.
{
"status": "healthy",
"message": "All systems operational",
"timestamp": "2026-06-27T12:00:00.000Z",
"apiVersion": "1",
"checks": {
"database": { "status": "healthy", "latencyMs": 4 },
"connectionPool": { "status": "healthy" },
"process": { "status": "healthy", "uptimeSeconds": 86400 }
}
}
/api/v1/health/ready
Readiness probe — prêt à servir du trafic (base de données requise). Utile pour Kubernetes / load balancers.
/api/v1/health/live
Liveness probe — le processus Node.js répond. Ne vérifie pas MySQL.
Tableau de bord visuel : /system-health · Détails complets avec ?token= ou en-tête X-Health-Token si HEALTH_DETAIL_TOKEN est configuré.
Authentification
POST
/api/v1/auth/login
Connexion utilisateur pour obtenir un token JWT
{
"identifier": "user@example.com",
"password": "password"
}
/api/v1/auth/login
Connexion utilisateur pour obtenir un token JWT
{
"identifier": "user@example.com",
"password": "password"
}
Commandes
POST
/api/v1/orders
Créer une commande (JWT requis). Le téléphone est obligatoire, le reste est optionnel.
Authorization: Bearer <token> (rôles : admin, reseller, agent)
{
"customerPhone": "+1234567890", // Obligatoire (nouveau nom)
"customerPhone1": "+1234567890", // Obligatoire si customerPhone absent (ancien nom)
"customerPhone2": "+1234567891", // Optionnel (téléphone secondaire)
"customerName": "John Doe", // Optionnel
"customerAddress": "123 Main St", // Optionnel (nouveau nom)
"address": "123 Main St", // Optionnel (ancien nom)
"customerCity": "Tunis", // Optionnel (nouveau nom)
"ville": "Tunis", // Optionnel (ancien nom)
"customerGovernorate": "Tunis", // Optionnel (nouveau nom)
"gouvernaurat": "Tunis", // Optionnel (ancien nom)
"customerZipCode": "1000", // Optionnel (code postal)
"notes": "Instructions de livraison", // Optionnel
"source": "manual", // Optionnel (défaut : "manual")
"status": "pending", // Optionnel (statut initial)
"resellerId": 12, // Admin uniquement
"supplierId": 3, // Admin uniquement
"shippingOption": "paid", // Optionnel : "paid" active shippingCost
"shippingCost": 8.5, // Optionnel : utilisé si shippingOption = "paid"
"shipping": 8.5, // Optionnel : ancien champ de livraison
"products": [
{
"productId": 1,
"quantity": 2,
"price": 99.99, // Nouveau nom de champ
"notes": "Variante: Bleu / Taille M"
},
{
"productId": 2,
"quantity": 1,
"unitPrice": 49.99, // Ancien nom de champ (supporté)
"notes": "Option: Pack cadeau"
}
]
}
Champs acceptés (exact)
- • customerPhone / customerPhone1: string, obligatoire (l'un des deux)
- • customerPhone2: string, optionnel
- • customerName: string, optionnel
- • customerAddress / address: string, optionnel
- • customerCity / ville: string, optionnel
- • customerGovernorate / gouvernaurat: string, optionnel
- • customerZipCode: string ou number, optionnel
- • notes: string, optionnel
- • source: enum, optionnel (voir ci-dessous)
- • status: enum, optionnel (voir ci-dessous)
- • shippingOption: string, optionnel (valeur reconnue :
paid)
- • shippingCost / shipping: number, optionnel (>= 0)
- • products: array, obligatoire (1–2 items)
Schéma des items produits (exact)
- • productId: integer, obligatoire (ID produit fournisseur)
- • quantity: integer, obligatoire (min 1)
- • price / unitPrice: number, obligatoire (> 0)
- • notes: string, obligatoire si la commande ne vient pas de Converty (variante/option)
- • productImage: non requis dans la requête (l'image est récupérée depuis le mapping produit)
Champs selon le rôle
- • Admin uniquement :
resellerId (integer) et supplierId (integer) obligatoires.
- • Reseller/Agent :
resellerId et supplierId sont ignorés (pris depuis l'utilisateur authentifié).
Règle Converty vs autres sources
Les commandes issues de Converty utilisent l'image du mapping produit côté serveur.
Pour les commandes provenant d'autres sources (site web, scraping, API externe), chaque item doit inclure
notes (variante/option). L'image est récupérée côté serveur depuis le mapping produit.
Si vous utilisez Converty, configurez d'abord le mapping produits avant d'envoyer des commandes.
Pour récupérer les IDs produits fournisseur, utilisez /api/v1/converty/product-mappings (mapping Converty → fournisseur)
ou /api/v1/products. Ne partagez pas cost_price (privé).
Contraintes de validation
- • customerPhone OR customerPhone1: Obligatoire - téléphone principal
- • customerName: Optionnel - nom complet
- • customerPhone2: Optionnel - téléphone secondaire
- • customerAddress OR address: Optionnel - adresse
- • customerCity OR ville: Optionnel - ville
- • customerGovernorate OR gouvernaurat: Optionnel - gouvernorat
- • customerZipCode: Optionnel - code postal
- • notes: Optionnel - notes
- • source: Optionnel - source (par défaut "manual")
- • status: Optionnel - pending, confirmed, canceled, abandoned, not_reached, phone_closed, rapported, not_interested, more_information, not_available
- • products: 1-2 items, chacun avec productId fournisseur (int), quantity (int ≥ 1), price ou unitPrice (number > 0), notes + productImage requis hors Converty
Valeurs enum de source
- manualCommande créée manuellement (par défaut)
- scrapedCommande issue du scraping
- apiCommande via API externe
- convertyCommande via Converty
- phone_callCommande par appel téléphonique
- whatsappCommande via WhatsApp
- facebook_pageCommande via page Facebook
- instagramCommande via Instagram
- sur_placeCommande sur place
- tiktokCommande via TikTok
- site_web / site webCommande via site web
- autreAutre source
Valeurs enum de statut
- • pending, confirmed, canceled, abandoned
- • not_reached, phone_closed, rapported
- • not_interested, more_information, not_available
Si source est sur_place, le système force status = delivered, marque le paiement comme payé, et met "Sur place" pour la ville/gouvernorat si manquants.
Réponse :
{
"success": true,
"message": "Order created successfully",
"orderNumber": "ORD-1755436083209-123",
"orderStatus": "pending",
"order": {
"id": 123,
"orderNumber": "ORD-1755436083209-123",
"status": "pending",
"total": 249.97,
"customerName": "John Doe",
"customerPhone": "+1234567890",
"customerPhone2": "+1234567891",
"customerAddress": "123 Main St",
"customerCity": "Tunis",
"customerGovernorate": "Tunis",
"customerZipCode": "1000",
"notes": "Instructions de livraison",
"source": "manual",
"barcode": "ORD-1755436083209-123"
}
}
/api/v1/orders
Créer une commande (JWT requis). Le téléphone est obligatoire, le reste est optionnel.
Authorization: Bearer <token> (rôles : admin, reseller, agent)
{
"customerPhone": "+1234567890", // Obligatoire (nouveau nom)
"customerPhone1": "+1234567890", // Obligatoire si customerPhone absent (ancien nom)
"customerPhone2": "+1234567891", // Optionnel (téléphone secondaire)
"customerName": "John Doe", // Optionnel
"customerAddress": "123 Main St", // Optionnel (nouveau nom)
"address": "123 Main St", // Optionnel (ancien nom)
"customerCity": "Tunis", // Optionnel (nouveau nom)
"ville": "Tunis", // Optionnel (ancien nom)
"customerGovernorate": "Tunis", // Optionnel (nouveau nom)
"gouvernaurat": "Tunis", // Optionnel (ancien nom)
"customerZipCode": "1000", // Optionnel (code postal)
"notes": "Instructions de livraison", // Optionnel
"source": "manual", // Optionnel (défaut : "manual")
"status": "pending", // Optionnel (statut initial)
"resellerId": 12, // Admin uniquement
"supplierId": 3, // Admin uniquement
"shippingOption": "paid", // Optionnel : "paid" active shippingCost
"shippingCost": 8.5, // Optionnel : utilisé si shippingOption = "paid"
"shipping": 8.5, // Optionnel : ancien champ de livraison
"products": [
{
"productId": 1,
"quantity": 2,
"price": 99.99, // Nouveau nom de champ
"notes": "Variante: Bleu / Taille M"
},
{
"productId": 2,
"quantity": 1,
"unitPrice": 49.99, // Ancien nom de champ (supporté)
"notes": "Option: Pack cadeau"
}
]
}
Champs acceptés (exact)
- • customerPhone / customerPhone1: string, obligatoire (l'un des deux)
- • customerPhone2: string, optionnel
- • customerName: string, optionnel
- • customerAddress / address: string, optionnel
- • customerCity / ville: string, optionnel
- • customerGovernorate / gouvernaurat: string, optionnel
- • customerZipCode: string ou number, optionnel
- • notes: string, optionnel
- • source: enum, optionnel (voir ci-dessous)
- • status: enum, optionnel (voir ci-dessous)
- • shippingOption: string, optionnel (valeur reconnue :
paid) - • shippingCost / shipping: number, optionnel (>= 0)
- • products: array, obligatoire (1–2 items)
Schéma des items produits (exact)
- • productId: integer, obligatoire (ID produit fournisseur)
- • quantity: integer, obligatoire (min 1)
- • price / unitPrice: number, obligatoire (> 0)
- • notes: string, obligatoire si la commande ne vient pas de Converty (variante/option)
- • productImage: non requis dans la requête (l'image est récupérée depuis le mapping produit)
Champs selon le rôle
- • Admin uniquement :
resellerId(integer) etsupplierId(integer) obligatoires. - • Reseller/Agent :
resellerIdetsupplierIdsont ignorés (pris depuis l'utilisateur authentifié).
Règle Converty vs autres sources
Les commandes issues de Converty utilisent l'image du mapping produit côté serveur.
Pour les commandes provenant d'autres sources (site web, scraping, API externe), chaque item doit inclure
notes (variante/option). L'image est récupérée côté serveur depuis le mapping produit.
Si vous utilisez Converty, configurez d'abord le mapping produits avant d'envoyer des commandes.
Pour récupérer les IDs produits fournisseur, utilisez /api/v1/converty/product-mappings (mapping Converty → fournisseur)
ou /api/v1/products. Ne partagez pas cost_price (privé).
Contraintes de validation
- • customerPhone OR customerPhone1: Obligatoire - téléphone principal
- • customerName: Optionnel - nom complet
- • customerPhone2: Optionnel - téléphone secondaire
- • customerAddress OR address: Optionnel - adresse
- • customerCity OR ville: Optionnel - ville
- • customerGovernorate OR gouvernaurat: Optionnel - gouvernorat
- • customerZipCode: Optionnel - code postal
- • notes: Optionnel - notes
- • source: Optionnel - source (par défaut "manual")
- • status: Optionnel - pending, confirmed, canceled, abandoned, not_reached, phone_closed, rapported, not_interested, more_information, not_available
- • products: 1-2 items, chacun avec productId fournisseur (int), quantity (int ≥ 1), price ou unitPrice (number > 0), notes + productImage requis hors Converty
Valeurs enum de source
- manualCommande créée manuellement (par défaut)
- scrapedCommande issue du scraping
- apiCommande via API externe
- convertyCommande via Converty
- phone_callCommande par appel téléphonique
- whatsappCommande via WhatsApp
- facebook_pageCommande via page Facebook
- instagramCommande via Instagram
- sur_placeCommande sur place
- tiktokCommande via TikTok
- site_web / site webCommande via site web
- autreAutre source
Valeurs enum de statut
- • pending, confirmed, canceled, abandoned
- • not_reached, phone_closed, rapported
- • not_interested, more_information, not_available
Si source est sur_place, le système force status = delivered, marque le paiement comme payé, et met "Sur place" pour la ville/gouvernorat si manquants.
Réponse :
{
"success": true,
"message": "Order created successfully",
"orderNumber": "ORD-1755436083209-123",
"orderStatus": "pending",
"order": {
"id": 123,
"orderNumber": "ORD-1755436083209-123",
"status": "pending",
"total": 249.97,
"customerName": "John Doe",
"customerPhone": "+1234567890",
"customerPhone2": "+1234567891",
"customerAddress": "123 Main St",
"customerCity": "Tunis",
"customerGovernorate": "Tunis",
"customerZipCode": "1000",
"notes": "Instructions de livraison",
"source": "manual",
"barcode": "ORD-1755436083209-123"
}
}
Mapping produits (Converty)
GET
/api/v1/converty/product-mappings
Lister les mappings Converty ↔ fournisseur (sans cost_price)
{
"success": true,
"mappings": [
{
"id": 12,
"convertyProduct": { "id": 321, "name": "Produit A", "sku": "SKU-A", "price": 29.9 },
"supplierProduct": { "id": 7, "name": "Produit A", "code": "PA-01", "price": 29.9, "stock_quantity": 40 },
"converty_image": "https://cdn.commercy.net/converty/321.jpg",
"createdAt": "2026-01-19T10:00:00.000Z"
}
]
}
Utilisez supplierProduct.id comme productId dans l'API de commande.
POST
/api/v1/converty/product-mappings
Créer un mapping Converty ↔ fournisseur
{
"convertyProductId": 321,
"supplierProductId": 7
}
DELETE
/api/v1/converty/product-mappings/:id
Supprimer un mapping
GET
/api/v1/converty/check-mappings/:resellerId
Vérifier si les mappings existent pour un revendeur
/api/v1/converty/product-mappings
Lister les mappings Converty ↔ fournisseur (sans cost_price)
{
"success": true,
"mappings": [
{
"id": 12,
"convertyProduct": { "id": 321, "name": "Produit A", "sku": "SKU-A", "price": 29.9 },
"supplierProduct": { "id": 7, "name": "Produit A", "code": "PA-01", "price": 29.9, "stock_quantity": 40 },
"converty_image": "https://cdn.commercy.net/converty/321.jpg",
"createdAt": "2026-01-19T10:00:00.000Z"
}
]
}
Utilisez supplierProduct.id comme productId dans l'API de commande.
/api/v1/converty/product-mappings
Créer un mapping Converty ↔ fournisseur
{
"convertyProductId": 321,
"supplierProductId": 7
}
/api/v1/converty/product-mappings/:id
Supprimer un mapping
/api/v1/converty/check-mappings/:resellerId
Vérifier si les mappings existent pour un revendeur
Exemples de code
JavaScript / Node.js
const api = new CommercyAPI({
baseURL: 'https://api.commercy.net',
apiVersion: 'v1'
});
// Connexion
const loginResult = await api.login('user@example.com', 'password');
// Lister les commandes
const orders = await api.getOrders({ limit: 10, page: 1 });
// Créer une commande
const newOrder = await api.createOrder({
customerName: 'John Doe',
products: [{ productId: 1, quantity: 2 }]
});
Python
import requests
class CommercyAPI:
def __init__(self, base_url, token):
self.base_url = f"{base_url}/api/v1"
self.headers = {
'Authorization': f'Bearer {token}',
'Content-Type': 'application/json'
}
def get_orders(self, params=None):
response = requests.get(
f"{self.base_url}/orders",
headers=self.headers,
params=params
)
return response.json()
# Utilisation
api = CommercyAPI('https://api.commercy.net', 'your-token')
orders = api.get_orders({'limit': 10, 'page': 1})
SDK & Outils
JavaScript SDK
SDK complet avec tous les endpoints et la gestion d'erreurs
Postman Collection
Collection Postman prête à l'emploi pour les tests
Exemples
Exemples complets et bonnes pratiques
Format de réponse
Réponse standard
{
"success": true,
"data": {
"id": 123,
"customerName": "John Doe",
"status": "pending",
"createdAt": "2024-01-15T10:30:00.000Z"
},
"message": "Order created successfully",
"timestamp": "2024-01-15T10:30:00.000Z"
}
Réponse paginée
{
"success": true,
"data": [
{
"id": 1,
"customerName": "John Doe",
"status": "pending"
}
],
"pagination": {
"page": 1,
"limit": 10,
"total": 100,
"totalPages": 10,
"hasNext": true,
"hasPrev": false
},
"timestamp": "2024-01-15T10:30:00.000Z"
}
Gestion des erreurs
Codes de statut HTTP
Format de réponse d'erreur
{
"success": false,
"error": "Validation error",
"message": "Invalid input data",
"timestamp": "2024-01-15T10:30:00.000Z",
"details": {
"field": "email",
"message": "Email is required"
}
}
Support & Ressources
Obtenir de l'aide
- • WhatsApp : +21620940425
- • Email : mouhameddhiafajria@gmail.com
Conseils de performance
- • Utilisez la pagination pour les gros volumes
- • Gérez les erreurs correctement
- • Mettez en cache les données fréquentes
- • Utilisez la compression pour accélérer les réponses
Dépannage
Problèmes courants
"Invalid Date" dans les tableaux
Cela arrive quand les dates ne sont pas au bon format. Utilisez le format ISO : YYYY-MM-DDTHH:mm:ss.sssZ
Erreurs de validation
Vérifiez les champs obligatoires et les bons noms de champs (ancien ou nouveau format).
MySQL / base de données
Si l'API répond mais les commandes échouent, ouvrez le tableau de bord santé système — un statut ECONNREFUSED indique que MySQL est arrêté.
Problèmes d'authentification
Vérifiez l'envoi d'un JWT valide dans l'en-tête Authorization : Bearer YOUR_TOKEN
Corrections rapides
Formatage des dates
Utilisez new Date().toISOString() pour un format correct en JavaScript.
Noms des champs
Les anciens et nouveaux noms sont supportés. Utilisez le format déjà utilisé côté frontend.
Version de l'API
Utilisez toujours les endpoints /api/v1/ pour les dernières fonctionnalités et la rétrocompatibilité.