Intégrer votre site à ABMCY Core

Guide de référence pour connecter votre site, votre application ou vos scripts à la plateforme ABMCY — commandes, mesures sur-mesure, paiements, catalogue et comptes clients.

Authentification

Trois accès distincts, à ne pas confondre.

TypeUtilisé parComment
Clé API tenantVotre site, vos scriptsX-API-Key: pk_live_...
JWT personnelUn membre de votre équipePOST /auth/login puis Bearer
JWT client finalUn acheteur (ex: Fatou)POST /auth/customer/login puis Bearer

Pour une intégration technique, utilisez la clé API tenant — c'est la méthode recommandée. Elle vous a été communiquée à la création de votre compte, ou se trouve dans votre dashboard.

Exemple : appeler l'API avec votre clé

bash
# Toutes les routes tenant acceptent ce header
curl https://api.abmcy.com/orders \
  -H "X-API-Key: pk_live_votre_cle_ici"

Connexion personnel (JWT)

POST/auth/loginpublic
{
  "tenant_slug": "votre-boutique",
  "email": "[email protected]",
  "password": "votre-mot-de-passe"
}
200 OK
{ "token": "eyJhbGciOi..." }

Utilisez ensuite Authorization: Bearer <token> sur les mêmes routes que X-API-Key. Le token expire après 24h.

Format des réponses

Toutes les erreurs suivent la même structure JSON.

{
  "error": {
    "code": "validation_error",
    "message": "Données invalides."
  }
}

Un succès est un objet/tableau JSON (200, 201) ou une réponse vide (204). Un 202 signifie une demande acceptée mais traitée de façon asynchrone.

Commandes

Créer, consulter et faire évoluer les commandes de vos clients.

Créer une commande

POST/ordersX-API-Key
{
  "customer_name": "Fatou Diop",
  "customer_phone": "+221771234567",
  "customer_email": "[email protected]",
  "total_amount": 25000,
  "measurements": { "poitrine": 92, "taille": 80 }
}
201 Created
{
  "id": "c5a72dc0-...",
  "order_number": "ORD-123456789",
  "customer_name": "Fatou Diop",
  "customer_phone": "+221771234567",
  "total_amount": 25000,
  "status": "pending",
  "created_at": "2026-09-07T12:00:00Z"
}

Si customer_email est fourni, un email de confirmation part automatiquement — un échec d'envoi ne fait jamais échouer la commande.

Commande sur-mesure (avec tissu)

POST/custom-ordersX-API-Key
{
  "customer_name": "Fatou Diop",
  "customer_phone": "+221771234567",
  "shipping_address": "Dakar, Sénégal",
  "total_amount": 45000,
  "measurements": { "poitrine": 92, "hanches": 98 },
  "fabric_id": "uuid-du-tissu",
  "fabric_source": "maison",
  "notes": "Manches longues souhaitées"
}

fabric_source : maison (tissu du catalogue), envoi_photo (photo envoyée par le client), ou conseil_atelier.

Lister, consulter, modifier

GET/orders
GET/orders/{orderID}
GET/orders/{orderID}/history
[
  { "status": "pending", "created_at": "2026-09-07T12:00:00Z" },
  { "status": "paid", "comment": "Paiement confirmé", "created_at": "2026-09-07T12:05:00Z" }
]
PATCH/orders/{orderID}
{ "shipping_address": "Nouvelle adresse", "notes": "..." }

Seules les commandes pending ou confirmed restent modifiables — sinon order_not_editable.

Mesures sur-mesure

POST/measurements
{
  "customer_name": "Fatou Diop",
  "customer_phone": "+221771234567",
  "gender": "femme",
  "values": {
    "poitrine": 92, "taille": 80, "hanches": 98,
    "epaules": 40, "manches": 58, "longueur": 110
  }
}

gender : femme ou homme. Le contenu de values est libre — définissez vos propres champs (ex: ajoutez pantalon pour un homme).

Upload d'images

POST/uploads/image
Content-Type: multipart/form-data

[email protected]
201 Created
{ "id": "uuid", "url": "https://...", "size_bytes": 245678 }
25 Mo maximum par fichier. Chaque tenant a un quota de stockage (5 Go par défaut) — au-delà, storage_quota_exceeded.

Cette route téléverse un fichier brut (multipart/form-data) vers le stockage ABMCY et renvoie son URL publique définitive. Elle ne rattache l'image à aucun produit — voir Rattacher une image à un produit ci-dessous pour l'associer à un article de votre catalogue, ou POST /gallery pour l'afficher dans votre galerie de réalisations.

Paiements

POST/payments/init
{
  "order_id": "uuid-de-la-commande",
  "amount": 25000,
  "customer_name": "Fatou Diop",
  "customer_phone": "+221771234567",
  "return_url": "https://votre-site.com/merci"
}
200 OK
{ "payment_url": "https://checkout.exemple.com/..." }

Redirigez votre client vers payment_url — Wave, Orange Money, MTN MoMo ou carte selon son choix. Une fois confirmé, la commande passe automatiquement à paid, sans action de votre part.

Acompte 50 % et solde

Une commande peut se payer en plusieurs fois : un acompte de 50 % en ligne à la commande, puis le solde après la livraison — par lien de paiement ou en espèces au livreur. Les paiements en ligne (Wave, Orange Money, Free Money, carte) passent par ABMCY Core Payment.

POST/orders/{orderID}/pay
{ "part": "deposit", "return_url": "https://votre-site.com/#/paiement-confirme" }
201 Created
{
  "payment": { "id": "uuid", "kind": "deposit", "amount_fcfa": 5700,
               "status": "pending", "payment_url": "https://core.diarra.app/..." },
  "summary": { "total_fcfa": 11400, "paid_fcfa": 0, "remaining_fcfa": 11400, "deposit_fcfa": 5700 }
}

part : deposit (la moitié, tant que rien n'est payé), balance ou full (tout le reste). Redirigez le client vers payment_url. Le montant est toujours calculé par l'API, jamais fourni par votre site.

GET/orders/{orderID}/payments

Situation de paiement : total, payé, reste, et chaque paiement avec ses frais (fee_fcfa), son net (net_fcfa) et le dernier statut lu chez l'agrégateur (provider_status).

POST/orders/{orderID}/payments/cash

Le reste a été payé en espèces au livreur. JWT du personnel obligatoire — refusé avec une clé API. Quand une commande passe à delivered avec un solde, le client reçoit automatiquement le lien du solde par email.

Revenus et bilan

Réservé au personnel connecté (JWT) : ces chiffres ne sont jamais lisibles avec une clé API.

GET/finance/statement?from=2026-10-01&to=2026-10-31
{
  "orders": { "count": 12, "amount_fcfa": 162000 },
  "collected_fcfa": 98000,
  "online": { "count": 8, "gross_fcfa": 76000, "fee_fcfa": 1520, "net_fcfa": 74480 },
  "cash": { "count": 3, "amount_fcfa": 22000 },
  "pending": { "count": 2, "amount_fcfa": 13500 },
  "settled_fcfa": 50000,
  "all_time": { "balance_due_fcfa": 24480, "outstanding_fcfa": 64000, "open_orders": 5 },
  "daily": [ { "date": "2026-10-03", "online_fcfa": 12000, "cash_fcfa": 0 } ],
  "payments": [ ... ],
  "settlements": [ ... ]
}

balance_due_fcfa : ce qu'ABMCY doit reverser à la boutique (net encaissé en ligne − déjà reversé). outstanding_fcfa : ce que les clients doivent encore. Sans dates : le mois en cours.

POST/finance/statement/email?from=…&to=…

Envoie le bilan de la période au propriétaire de la boutique.

GET/finance/open-orders

Commandes avec un reste à payer, pour envoyer un lien.

POST/order-payments/{paymentID}/refresh

Revérifie un paiement en ligne auprès de l'agrégateur (statut, frais, motif d'échec) — utile si un client dit avoir payé.

Notifications email

POST/notifications/email
{
  "to": "[email protected]",
  "subject": "Votre commande est prête",
  "html": "<p>Bonjour...</p>",
  "template": "order_ready"
}
202 Accepted
100 emails / jour par tenant, remis à zéro chaque minuit. Au-delà : email_quota_exceeded.

Le contenu HTML que vous envoyez ici est utilisé tel quel. Les emails générés automatiquement par ABMCY (confirmation de commande, bienvenue, réinitialisation de mot de passe) utilisent un gabarit visuel commun — même mise en page, mêmes couleurs — pour rester cohérents avec vos autres communications.

Catalogue — optionnel

Six services indépendants — cinq pour le catalogue (produits, tissus, panier, galerie, avis) et un pour la gestion d'équipe — chacun activé à la demande pour votre compte selon votre activité. Vérifiez votre statut :

GET/features
{
  "products_enabled": true,
  "fabrics_enabled": true,
  "cart_enabled": false,
  "gallery_enabled": true,
  "reviews_enabled": true,
  "staff_enabled": false
}

Chacun activable séparément selon votre activité — un atelier de couture sur-mesure peut par exemple avoir products_enabled, fabrics_enabled et gallery_enabled sans cart_enabled (les commandes passent par /custom-orders plutôt qu'un panier classique) ni staff_enabled tant qu'un seul compte suffit. Si un service est désactivé, ses routes renvoient un 403 avec un code dédié : products_not_enabled, fabrics_not_enabled, cart_not_enabled, gallery_not_enabled, reviews_not_enabled ou staff_not_enabled.

Activation. Ces services ne s'activent pas eux-mêmes : contactez ABMCY pour qu'un opérateur les bascule depuis le dashboard admin. Un nouveau compte reçoit un préréglage selon son secteur d'activité à la création (couture sur-mesure → produits + tissus + galerie + avis ; commerce général ou produit numérique → produits + panier + avis ; autre → rien de pré-activé) — un point de départ, pas une limite : n'importe quelle combinaison peut être activée ou désactivée ensuite.

Produits — modèle générique

attributes est un objet libre : tailles/couleurs pour la couture, poids/marque pour un commerce général, lien de téléchargement pour un produit numérique — à vous de choisir.

POST/products
{
  "name": "Robe wax",
  "price": 35000,
  "category": "robes",
  "sku": "ROB-001",
  "stock_quantity": 5,
  "attributes": { "tailles": ["S","M","L"], "couleurs": ["Bleu nuit"] },
  "is_featured": true
}
GET/products?category=robes&sort=price_asc
GET/products/{productID}
{
  "id": "uuid",
  "name": "Robe wax",
  "price": 35000,
  "attributes": { "tailles": ["S","M","L"] },
  "images": [
    { "id": "uuid", "url": "https://cdn.votre-boutique.com/..." }
  ]
}

sort : price_asc, price_desc, newest, featured. Le tableau images peut contenir plusieurs photos par produit — la première sert de vignette dans les dashboards ABMCY.

Rattacher une image à un produit

Il n'y a pas de champ image direct sur POST /products — l'image se rattache en deux temps, comme pour tout fichier sur ABMCY :

POST/uploads/image
1. Téléversez le fichier — multipart/form-data, champ "image"
   Réponse : { "id": "...", "url": "https://cdn.votre-boutique.com/..." }

2. Conservez l'url obtenue et placez-la dans les attributes du produit (par convention, la clé image_url) lors de sa création ou de sa mise à jour — c'est ce que les dashboards ABMCY lisent pour afficher la vignette du produit dans le catalogue.

{
  "name": "Robe wax",
  "price": 35000,
  "attributes": {
    "tailles": ["S","M","L"],
    "image_url": "https://cdn.votre-boutique.com/.../robe-wax.jpg"
  }
}

Exemple réel — un catalogue de plusieurs dizaines de produits importés avec cette méthode, chaque photo étant à la fois l'image du produit et ajoutée à la galerie (POST /gallery) pour apparaître aussi dans les réalisations de la boutique.

Tissus & galerie

GET/fabrics
POST/fabrics
{ "name": "Wax hollandais", "extra_price": 5000, "image_url": "..." }
POST/fabrics/upload
multipart/form-data, champ "image" — photo envoyée par le client
POST/gallery
{
  "image_url": "https://cdn.votre-boutique.com/.../photo.jpg",
  "category": "femme",
  "caption": "Robe wax sur mesure"
}
GET/gallery?category=femme
[
  {
    "id": "uuid",
    "image_url": "https://cdn.votre-boutique.com/...",
    "category": "femme",
    "caption": "Robe wax sur mesure"
  }
]

category : femme, homme, sur_mesure, artisanat. Contrairement au produit (où l'image vit dans attributes), la galerie a un vrai champ image_url dédié — c'est la vue pensée pour être affichée en grille de photos, dans votre dashboard comme sur un site public.

Panier

Sauvegardé côté serveur, identifié par un cart_token opaque (généré automatiquement si absent).

POST/cart
{ "product_id": "uuid", "size": "M", "color": "Bleu", "quantity": 1 }
GET/cart?cart_token=...
DELETE/cart/{itemID}?cart_token=...

Avis clients

Créés non publiés par défaut — modération requise avant affichage public.

POST/reviews
{ "order_id": "uuid", "rating": 5, "comment": "Très satisfaite !" }
GET/reviews/pending
POST/reviews/{reviewID}/publish

Comptes clients finaux

Vos acheteurs peuvent suivre leurs commandes en ligne, indépendamment de votre clé API.

POST/auth/customer/registerpublic
{ "tenant_slug": "votre-boutique", "phone": "+221771234567", "password": "motdepasse123" }

Le client doit déjà exister (créé lors de sa première commande) — sinon customer_not_found.

POST/auth/customer/loginpublic
POST/auth/customer/forgot-passwordpublic
POST/auth/customer/reset-passwordpublic

Une fois connecté (Bearer token)

POST/auth/customer/logout
GET/auth/customer/me
PATCH/auth/customer/me
{ "name": "...", "shipping_address": "..." }

Clients finaux — vus côté tenant

Ce qui précède est ce que le client lui-même peut faire. Votre équipe peut de son côté consulter et corriger le dossier de n'importe quel client — toujours accessible, sans feature flag, mais réservé au JWT personnel comme la gestion d'équipe (staff_login_required si connecté seulement par clé API).

GET/customers
GET/customers/{customerID}
PATCH/customers/{customerID}
{ "name": "...", "phone": "...", "email": "...", "shipping_address": "..." }

Contrairement à PATCH /auth/customer/me (le client ne peut pas changer son propre numéro, c'est son identifiant), le staff peut corriger le téléphone d'un client depuis le dashboard — utile pour une faute de frappe à la prise de commande.

PUT/customers/{customerID}/password
{ "new_password": "nouveaumotdepasse123" }

Définit directement un nouveau mot de passe, sans passer par /auth/customer/forgot-password — utile quand un client appelle la boutique parce qu'il a oublié son mot de passe, ou n'en a jamais défini. Le mot de passe précédent (le cas échéant) est immédiatement remplacé.

Gestion de l'équipe — optionnel

Contrôlé par staff_enabled (voir GET /features plus haut) — jamais activé automatiquement, quel que soit votre secteur d'activité, puisqu'avoir plusieurs comptes n'a rien à voir avec ce que vous vendez. Si désactivé, ces routes renvoient staff_not_enabled. Une fois activées, elles restent en plus réservées aux comptes connectés par JWT personnel — une clé API seule ne suffit pas (staff_login_required).

GET/staff
POST/staffowner
{ "email": "[email protected]", "password": "...", "role": "staff" }
PUT/staff/{userID}/activeowner
{ "is_active": false }

POST /auth/logout n'exige que le JWT personnel — pas staff_enabled — puisqu'un membre déjà connecté doit toujours pouvoir se déconnecter :

POST/auth/logout

Codes d'erreur

Tous suivent le format {"error":{"code","message"}} décrit plus haut.

CodeHTTPSignification
missing_api_key401Aucune clé API fournie
invalid_api_key403Clé invalide ou compte désactivé
unauthorized401Identifiants invalides
forbidden403Droits insuffisants
staff_login_required403JWT personnel requis, pas une clé API
not_found404Ressource introuvable
order_already_paid409Commande déjà entièrement réglée
deposit_already_paid409L'acompte est déjà réglé : demandez le solde
payment_provider_error502Agrégateur de paiement momentanément indisponible
customer_not_found404Aucun profil pour ce téléphone
unknown_config_key404Clé de configuration inconnue
validation_error422Données invalides ou incomplètes
products_not_enabled403Service produits non activé pour ce compte
fabrics_not_enabled403Service tissus non activé pour ce compte
cart_not_enabled403Service panier non activé pour ce compte
gallery_not_enabled403Service galerie non activé pour ce compte
reviews_not_enabled403Service avis non activé pour ce compte
staff_not_enabled403Service gestion d'équipe non activé pour ce compte
order_not_editable409Commande plus modifiable
invalid_or_expired_token400Lien de réinitialisation invalide/expiré
file_too_large413Fichier > 25 Mo
storage_quota_exceeded413Quota de stockage dépassé
storage_not_configured503Stockage pas encore configuré côté ABMCY
payment_not_configured503Paiements pas encore configurés côté ABMCY
email_quota_exceeded429Quota de 100 emails/jour dépassé
rate_limited429Trop de requêtes — ralentissez
internal_error500Erreur interne — contactez ABMCY
Des questions ? Contactez l'équipe ABMCY. — Documentation ABMCY Core Multi-Tenant.