Cabine.ai est désormais disponible sur Shopify. Installer l'application →

API Reference

Documentation API

API REST pour intégrer la cabine d'essayage virtuel IA dans vos boutiques e-commerce, et tracker les conversions générées.

Base URL : https://cabine.ai/api · V1 (essayage produit unique) : /v1/* · V2 (personal shopper Looks) : /v2/* · Format : application/json

Authentification

Toutes les requêtes nécessitent une clé API dans l'en-tête HTTP. Générez votre clé depuis Mon compte → Clés API. La même clé fonctionne pour V1 et V2.

Via l'en-tête X-Api-Key (recommandé)

X-Api-Key: vf_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Via Authorization Bearer

Authorization: Bearer vf_live_xxxxxxxxxxxxxxxxxxxxxxxx
⚠️ Ne commitez jamais votre clé API dans votre code source. Stockez-la dans une variable d'environnement ou dans la configuration de votre module.

Gestion des erreurs

Toutes les réponses d'erreur suivent ce format :

{
  "success": false,
  "error":   "error_code",
  "message": "Description lisible en français"
}
HTTPCode erreurEndpoint(s)Description
400invalid_jsontousCorps JSON malformé
401authentication_errortousClé API manquante, invalide ou révoquée
402no_active_subscription/generate · /look-tryonAucun abonnement actif sur ce compte
403model_not_allowed/generateModèle non inclus dans votre plan
404no_looks_available/look-tryonAucun Look publié disponible pour ce marchand (et/ou cette catégorie)
422invalid_paramtousParamètre manquant, invalide ou image non décodable
422invalid_param/generateprompt_type invalide (valeurs acceptées : mirror, universe, thematic)
422invalid_model/generateIdentifiant de modèle inconnu — consultez /models
422invalid_category/look-tryonCatégorie introuvable ou inactive
422no_usable_look/look-tryonAucun Look exploitable (le top match et ses alternatives n'ont pas de prompt try-on configuré)
429quota_exceeded/generate · /look-tryonQuota de crédits mensuel épuisé
500generation_failed/generate · /look-tryonErreur API Gemini ou génération impossible
500profile_analysis_failed/look-tryonL'analyse stylistique de la photo utilisateur a échoué
500matching_failed/look-tryonLe matcher n'a pu sélectionner aucun Look

Génération d'essayage V1

POST /api/v1/generate Lance une génération IA

Envoie deux images (produit + photo du client) et retourne une URL de téléchargement de l'image générée. Consomme 1 crédit par appel.

Sources d'images — 3 modes (mixables)

Les champs product_image_* et user_photo_* acceptent chacun 3 formats. Priorité : URL > base64 > multipart. Utilisez celui qui correspond à votre architecture.
ParamètreTypeDescription
IMAGE PRODUIT — fournir exactement l'un des 3
product_image_urlstringURLURL HTTPS publique de l'image produit. Doit être accessible depuis nos serveurs.
product_image_b64stringbase64Image encodée en base64, avec ou sans préfixe data:image/...;base64,. Min. 1 Ko décodé.
product_imagefilemultipartFichier image en multipart/form-data. Formats acceptés : JPEG, PNG, WebP.
PHOTO UTILISATEUR — fournir exactement l'un des 3
user_photo_urlstringURLURL HTTPS publique de la photo de la personne.
user_photo_b64stringbase64Photo encodée en base64.
user_photofilemultipartFichier photo en multipart/form-data.
OPTIONS
modelstringoptionnelIdentifiant du modèle IA. Défaut : gemini-3-pro-image-preview. Consultez GET /models pour la liste complète.
promptstringoptionnelInstructions personnalisées. Si absent, le prompt haute-fidélité par défaut est utilisé.
PROMPTS PAR CATÉGORIE — nouveaux champs optionnels
categorystringnouveauLibellé libre de la catégorie produit : "robe courte", "t-shirt", "lunettes de soleil"… cabine.ai associe automatiquement votre libellé à la meilleure catégorie interne via un matching intelligent (mots-clés + tokens + genre). Si une catégorie est reconnue ET qu'un prompt actif existe pour ce couple (catégorie, type), il remplace le prompt fourni.
prompt_typestringnouveauType de rendu souhaité : mirror (reflet réaliste), universe (univers éditorial premium) ou thematic (mise en scène thématique : fées, dinosaures, super-héros…). Défaut : mirror si category est fourni.
product_namestringnouveauNom complet du produit (ex : "Robe d'été rouge à motifs"). Améliore la précision du matching de catégorie, surtout si category est vague ou absent.
TRACKING — optionnels mais fortement recommandés pour le suivi des conversions
product_idintrecommandéID du produit côté CMS. Utilisé pour lier automatiquement les conversions à cette génération.
cart_idintrecommandéID du panier côté CMS. Clé de jonction principale avec l'endpoint POST /conversion.
customer_idintoptionnelID du client côté CMS. Pour filtrage et exports.
💡 Rétro-compatibilité garantie : si vous n'envoyez ni category, ni prompt_type, ni product_name, le comportement est strictement identique à l'API précédente. Aucune mise à jour de votre intégration n'est requise.

Mode 1 — URL publique (JSON)

curl -X POST https://cabine.ai/api/v1/generate \
  -H "X-Api-Key: vf_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "product_image_url": "https://maboutique.com/img/robe.jpg",
    "user_photo_url":    "https://maboutique.com/uploads/client.jpg",
    "product_id":         42,
    "cart_id":            67890,
    "customer_id":        12345
  }'

Mode 2 — Base64 ✅ recommandé pour PrestaShop

curl -X POST https://cabine.ai/api/v1/generate \
  -H "X-Api-Key: vf_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "product_image_b64": "data:image/jpeg;base64,/9j/4AAQ...",
    "user_photo_b64":    "data:image/jpeg;base64,/9j/4AAQ...",
    "product_id":         42,
    "cart_id":            67890,
    "customer_id":        12345
  }'

Mode 3 — Multipart/form-data (upload direct)

curl -X POST https://cabine.ai/api/v1/generate \
  -H "X-Api-Key: vf_live_xxx" \
  -F "product_image=@/chemin/robe.jpg" \
  -F "user_photo=@/chemin/client.jpg" \
  -F "product_id=42" \
  -F "cart_id=67890" \
  -F "customer_id=12345"

Mode 4 — Avec prompt premium « Univers » nouveau

Déclenche le prompt éditorial premium configuré côté cabine.ai pour la catégorie « robe courte ». Aucun prompt à fournir : le contenu est géré dans le back-office.

curl -X POST https://cabine.ai/api/v1/generate \
  -H "X-Api-Key: vf_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "product_image_b64": "data:image/jpeg;base64,/9j/4AAQ...",
    "user_photo_b64":    "data:image/jpeg;base64,/9j/4AAQ...",
    "category":           "robe courte",
    "prompt_type":        "universe",
    "product_name":       "Robe courte en soie rouge collection été",
    "product_id":         42,
    "cart_id":            67890
  }'

Mode 5 — Avec prompt « Thématisé » pour collection enfant nouveau

Pour une collection vêtements enfant avec mise en scène dinosaures. Le prompt thématique correspondant est configuré côté back-office cabine.ai pour la catégorie « t-shirt enfant ».

curl -X POST https://cabine.ai/api/v1/generate \
  -H "X-Api-Key: vf_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "product_image_b64": "data:image/jpeg;base64,/9j/4AAQ...",
    "user_photo_b64":    "data:image/jpeg;base64,/9j/4AAQ...",
    "category":           "t-shirt enfant",
    "prompt_type":        "thematic",
    "product_name":       "T-shirt enfant dinosaures collection Jurassic",
    "product_id":         142
  }'

Réponse succès (200)

{
  "success":             true,
  "result_url":          "https://cabine.ai/generation/a3f8...b2/download",
  "generation_id":       1042,
  "credits_used":        1,
  "credits_remaining":   163,
  "processing_time_ms":  8420
}

Champs de la réponse

ChampTypeDescription
successbooltrue si la génération a réussi
result_urlstringURL de téléchargement (token 64 hex, accessible sans authentification). Sauvegardez-la en BDD.
generation_idintID interne de la génération — à conserver pour le lien avec POST /conversion
credits_usedintCrédits consommés (toujours 1 par essayage)
credits_remainingintCrédits restants sur votre abonnement ce mois-ci
processing_time_msintDurée de traitement en millisecondes
result_url est accessible publiquement via un token sécurisé de 64 caractères. Durée de conservation 4 minutes avant suppression
Après expiration, la route retourne HTTP 410 Gone.

Prompts & catégories nouveau

cabine.ai permet d'utiliser des prompts spécialisés, configurés par catégorie de produit et par type de rendu, pour obtenir des résultats bien plus pertinents qu'avec un prompt générique. Les prompts sont gérés depuis votre back-office et appliqués automatiquement selon les informations que vous envoyez à l'API.

Principe de fonctionnement

À chaque appel à POST /generate, cabine.ai applique cette logique de priorité :

  1. Si category ou product_name est fourni : recherche d'une catégorie correspondante via matching intelligent. Si un prompt actif existe pour ce couple (catégorie × type), il est utilisé.
  2. Sinon, le champ prompt fourni par le client est utilisé (ancien comportement).
  3. Sinon, le prompt haute-fidélité par défaut de cabine.ai est utilisé.

Les trois types de prompts

TypeDescriptionCas d'usage
mirror Reflet réaliste du client dans son contexte naturel, portant le vêtement. Préservation maximale de l'identité faciale, de la morphologie et de la taille réelles. E-commerce classique, aide à la décision d'achat, réduction des retours.
universe Immersion éditoriale : le client est placé dans l'univers premium de la marque, avec direction artistique, lumière studio, ambiance de campagne publicitaire. Marques de luxe, collections premium, contenu social media, storytelling.
thematic Mise en scène thématique ludique : personnages, décors et ambiances imaginaires (fées, dinosaures, super-héros, pirates, espace, forêt enchantée…). Préserve l'identité faciale mais transpose le cadre dans un univers narratif. Collections enfants, collections saisonnières (Halloween, Noël), boutiques déguisements, marques de jouets, éditions limitées thématiques.

Matching intelligent des catégories

Vous n'avez pas besoin de connaître les slugs internes de cabine.ai. Envoyez simplement le libellé tel qu'il apparaît dans votre catalogue — le matcher trouve la meilleure correspondance grâce à un algorithme local (mots-clés, tokens, détection de genre) :

Libellé envoyéCatégorie résolue
"robe courte d'été"robe_courte
"mini robe rouge"robe_courte
"short pour homme"short_homme
"short femme plage"short_femme
"Ray-Ban aviateur"lunettes_soleil
"chemise lin oversize"chemise
"xyz1234"aucune — fallback sur prompt ou défaut
Astuce précision : combinez category (catégorie CMS) et product_name (nom complet du produit) pour le meilleur matching. Si votre CMS ne renseigne qu'un champ vague, envoyer les deux augmente les chances de résolution correcte.

Catégories disponibles par défaut

cabine.ai fournit un catalogue initial qui couvre la majorité des cas e-commerce mode & accessoires :

  • robe_longue
  • robe_courte
  • robe_mariee
  • robe_couture
  • jupe
  • pantalon
  • short_homme
  • short_femme
  • t_shirt
  • chemise
  • pull
  • veste
  • manteau
  • casquette
  • bonnet
  • chapeau
  • lunettes_soleil
  • lunettes_vue
  • chaussures
  • sac
  • maillot_bain

Besoin d'une catégorie supplémentaire (ex : bijouterie, montres, lingerie…) ? Contactez support@cabine.ai.

Gérer vos propres prompts

Les comptes Scale et Enterprise peuvent créer leurs propres prompts personnalisés depuis le back-office cabine.ai, section Prompts. Chaque prompt est lié à une catégorie et à un type, versionné automatiquement à chaque modification, avec historique et restauration en un clic.

Exemple complet — flux PrestaShop avec catégorie

// Récupération du produit + catégorie CMS côté PrestaShop
$product      = new Product((int) Tools::getValue('id_product'));
$categoryName = Category::getLinkRewrite($product->id_category_default, Context::getContext()->language->id);

$payload = json_encode([
    'product_image_b64' => 'data:image/jpeg;base64,' . base64_encode(file_get_contents($productImagePath)),
    'user_photo_b64'    => 'data:image/jpeg;base64,' . base64_encode(file_get_contents($userPhotoTmpPath)),
    'category'          => $categoryName,              // "robe-longue", "t-shirt-homme"…
    'prompt_type'       => 'universe',                // ou 'mirror'
    'product_name'      => $product->name[Context::getContext()->language->id],
    'product_id'        => (int) $product->id,
    'cart_id'           => (int) Context::getContext()->cart->id,
    'customer_id'       => (int) Context::getContext()->customer->id,
]);

Enregistrement de conversion V1

POST /api/v1/conversion Lie une commande à un essayage

Enregistre une conversion : une commande passée après qu'un client a effectué un essayage virtuel. L'API relie automatiquement la commande à la génération d'origine grâce au cart_id et au product_id envoyés lors de l'essayage.

Cet endpoint est idempotent : un second appel avec le même order_id retourne la conversion déjà enregistrée sans créer de doublon.

💡 Lien automatique : si vous avez fourni product_id et cart_id lors du POST /generate ou POST /look-tryon, l'API retrouve la génération correspondante et remplit linked_generation_id automatiquement.

Paramètres

ParamètreTypeDescription
order_idstringrequisID ou référence de la commande côté CMS (PrestaShop, WooCommerce…). Accepte les références alphanumériques.
product_idintrecommandéID du produit acheté côté CMS. Utilisé pour retrouver la génération d'origine.
cart_idintrecommandéID du panier à l'origine de la commande. Clé de jonction principale avec la génération.
customer_idintoptionnelID du client côté CMS.
metadataobjectoptionnelDonnées complémentaires libres : montant, devise, SKU, etc. (JSON arbitraire)

Exemple — appel depuis PrestaShop

curl -X POST https://cabine.ai/api/v1/conversion \
  -H "X-Api-Key: vf_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "order_id":    "PS-00012345",
    "product_id":  42,
    "cart_id":     67890,
    "customer_id": 12345,
    "metadata": {
      "amount":   89.90,
      "currency": "EUR",
      "sku":      "ROBE-BLEU-M"
    }
  }'

Réponse succès (201 Created)

{
  "success":               true,
  "conversion_id":         58,
  "linked_generation_id":  1042,
  "already_recorded":      false
}

Réponse — conversion déjà enregistrée (200, idempotent)

{
  "success":               true,
  "conversion_id":         58,
  "linked_generation_id":  1042,
  "already_recorded":      true
}

Champs de la réponse

ChampTypeDescription
successbooltrue dans tous les cas de succès
conversion_idintID interne de la conversion enregistrée
linked_generation_idint|nullID de la génération liée automatiquement, ou null si aucune génération trouvée pour ce cart_id + product_id
already_recordedbooltrue si la conversion existait déjà (réponse idempotente)

Intégration PrestaShop — hook actionOrderStatusPostUpdate

// À appeler depuis le hook de confirmation de commande
public function hookActionOrderStatusPostUpdate($params)
{
    $order  = $params['order'];
    $status = $params['newOrderStatus'];

    // Ne déclencher que sur commandes validées/payées
    if (!in_array($status->id, [2, 12])) return;

    foreach ($order->getProducts() as $product) {
        $payload = json_encode([
            'order_id'    => (string) $order->reference,
            'product_id'  => (int) $product['product_id'],
            'cart_id'     => (int) $order->id_cart,
            'customer_id' => (int) $order->id_customer,
            'metadata'    => [
                'amount'   => (float) $order->total_paid,
                'currency' => Context::getContext()->currency->iso_code,
                'sku'      => $product['reference'],
            ],
        ]);

        file_get_contents('https://cabine.ai/api/v1/conversion', false,
            stream_context_create(['http' => [
                'method'  => 'POST',
                'header'  => "X-Api-Key: vf_live_xxx\r\nContent-Type: application/json",
                'content' => $payload,
                'timeout' => 5,
                'ignore_errors' => true, // Ne pas bloquer la confirmation commande
            ]])
        );
    }
}
⚠️ L'endpoint conversion doit être appelé en tâche de fond ou avec un timeout court (5s). Ne laissez pas une éventuelle erreur réseau bloquer la confirmation de commande côté boutique.

Consulter son quota V1

GET /api/v1/quota Solde de crédits

Retourne le détail des crédits de l'abonnement actif. Aucun paramètre requis. Le quota retourné couvre les appels V1 et V2 (1 crédit chacun).

curl https://cabine.ai/api/v1/quota \
  -H "X-Api-Key: vf_live_xxx"

Réponse succès (200)

{
  "success":            true,
  "plan":               "Growth",
  "plan_slug":          "growth",
  "credits_total":      200,
  "credits_used":       37,
  "credits_bonus":      0,
  "credits_remaining":  163,
  "usage_percent":      18,
  "renews_at":          "2025-02-01"
}

Champs de la réponse

ChampTypeDescription
planstringNom lisible du plan actif
plan_slugstringIdentifiant machine du plan
credits_totalintCrédits mensuels inclus dans le plan
credits_usedintCrédits consommés ce mois-ci (V1 + V2)
credits_bonusintCrédits bonus ajoutés manuellement (hors quota mensuel)
credits_remainingintCrédits restants (inclut les crédits bonus)
usage_percentintPourcentage d'utilisation des crédits du plan (hors bonus)
renews_atstringDate de renouvellement du quota (format YYYY-MM-DD)

Modèles disponibles V1

GET /api/v1/models Liste les modèles selon votre plan

Retourne la liste des modèles IA disponibles et indique lesquels sont accessibles avec votre plan. Aucun paramètre requis.

curl https://cabine.ai/api/v1/models \
  -H "X-Api-Key: vf_live_xxx"

Réponse succès (200)

{
  "success": true,
  "models": [
    {
      "id":                     "gemini-3-pro-image-preview",
      "label":                  "Flash Image — défaut ✅",
      "credits_per_generation": 1,
      "available":             true
    }
  ]
}

Champs par modèle

ChampTypeDescription
idstringIdentifiant à passer dans le champ model de POST /generate
labelstringNom lisible du modèle
credits_per_generationint1 pour V1 — 2 pour V2 (look-tryon, ajoute l'analyse stylistique + matching)
availablebooltrue si le modèle est inclus dans votre plan actif

Look Try-On — Personal Shopper IA V2

L'API V2 propose un essayage virtuel d'un Look complet (tenue entière coordonnée par la marque) avec recommandation stylistique automatique. Le client envoie uniquement sa photo : Cabine.ai analyse son profil stylistique, sélectionne le Look le plus adapté parmi ceux publiés par le marchand, et génère l'essayage.

V1 vs V2
POST /api/v1/generate — essayage d'UN produit unique fourni en input par le client (1 crédit)
POST /api/v2/look-tryon — recommandation + essayage d'un LOOK COMPLET sélectionné par l'IA dans le catalogue marchand (1 crédit)

Pipeline complet

1
Vérification quota — l'abonnement doit disposer d'au moins 1 crédit
2
Analyse stylistique de la photo utilisateur — Gemini Vision extrait carnation, cheveux, morphologie, signal stylistique et couleurs portées (jamais retourné au client, usage interne uniquement)
3
Récupération des Looks candidats — uniquement les Looks au statut publié du marchand, filtrés optionnellement par category_id et/ou collection_id
4
Matching multi-critères — scoring pondéré sur couleurs (40 %), style (25 %), morphologie (20 %), carnation & cheveux (15 %). Tie-break sur le Look le moins récemment matché (rotation marketing)
5
Génération de l'essayage — Gemini Image avec le prompt try-on dédié au Look sélectionné (généré par Gemini à l'analyse du Look, structure rigoureuse mirror-style avec verrouillage absolu de l'identité utilisateur)
6
Génération déléguée — l'image d'essayage est produite via le même pipeline que /api/v1/generate (queue asynchrone, débit d'1 crédit, persistance, stockage). La V2 hérite ainsi de toute la robustesse de la V1.

Coût et architecture

L'appel V2 coûte 1 crédit, comme un essayage /api/v1/generate. L'analyse stylistique du profil et le matching des Looks ne consomment pas de crédit supplémentaire — seule la génération photoréaliste finale est facturée, exactement comme en V1. En interne, la V2 délègue la génération d'image au même orchestrateur que la V1 (file d'attente asynchrone, persistance, gestion d'erreur, stockage), ce qui garantit un comportement et une fiabilité identiques entre les deux endpoints.

Essayage d'un Look V2

POST /api/v2/look-tryon Recommandation + essayage d'un Look complet

Envoie uniquement la photo du client. L'API retourne le Look recommandé (avec raison de la sélection et liste des produits cliquables), l'image d'essayage générée, et 2 alternatives pour proposer un « Vous pourriez aussi aimer… ». Consomme 1 crédit par appel (comme un essayage V1).

Paramètres

ParamètreTypeDescription
PHOTO UTILISATEUR — fournir exactement l'un des 3
user_image_urlstringURLURL HTTPS publique de la photo de la personne. Doit être accessible depuis nos serveurs.
user_image_b64stringbase64Photo encodée en base64, avec ou sans préfixe data:image/...;base64,. Formats : JPEG, PNG, WebP.
user_photofilemultipartFichier photo en multipart/form-data.
FILTRES — optionnels (restreignent l'univers de matching)
category_idintoptionnelID d'une catégorie Cabine.ai existante. Restreint le matching aux Looks de cette catégorie. Si absent, tous les Looks publiés du marchand sont éligibles.
collection_idstringoptionnelID/GID libre de collection (Shopify GID, PrestaShop, etc.) tel que renseigné lors de la création des Looks. Permet de cibler une collection précise (« été 2026 », « capsule Pierre Hardy »…).
ESSAYAGE DIRECT — optionnel
look_idintoptionnelID d'un Look précis à essayer directement, sans recommandation. Typiquement le id d'une alternative reçue lors d'un précédent appel : le client demande « essayez plutôt celui-ci ». Voir Mode essayage direct ci-dessous.
⚠️ Pré-requis : au moins un Look publié doit exister dans votre catalogue Cabine.ai pour que l'endpoint retourne un résultat. Voir Créer des Looks.

Mode essayage direct (look_id)

Par défaut, l'endpoint fonctionne en mode recommandation : il analyse la photo, sélectionne le meilleur Look et renvoie 2 alternatives. Si le client souhaite ensuite essayer l'une de ces alternatives, rappelez le même endpoint en ajoutant son look_id — c'est le mode direct.

Le champ mode de la réponse vaut alors "direct" (vs "recommendation"). L'essayage est généré sur le Look demandé, et le bloc alternatives propose d'autres Looks du catalogue compatibles avec le profil.

🛡️ Garde-fous appliqués même en mode direct : le Look demandé doit appartenir à votre compte, être publié, et rester compatible avec le genre détecté sur la photo. Un Look féminin demandé pour un profil masculin renverra gender_mismatch — la cohérence prime sur la demande.

Le coût est identique (1 crédit), et la réponse a la même structure que le mode recommandation.

# 1er appel — recommandation
curl -X POST https://cabine.ai/api/v2/look-tryon \
  -H "Authorization: Bearer VOTRE_CLE" \
  -F user_photo=@client.jpg

# Réponse → alternatives: [{ "id": 47, ... }, { "id": 52, ... }]

# 2e appel — le client veut essayer l'alternative #47
curl -X POST https://cabine.ai/api/v2/look-tryon \
  -H "Authorization: Bearer VOTRE_CLE" \
  -F user_photo=@client.jpg \
  -F look_id=47

Mode 1 — URL publique (JSON, sans filtre)

curl -X POST https://cabine.ai/api/v2/look-tryon \
  -H "X-Api-Key: vf_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "user_image_url": "https://maboutique.com/uploads/client.jpg"
  }'

Mode 2 — Base64 ✅ recommandé pour intégrations CMS

curl -X POST https://cabine.ai/api/v2/look-tryon \
  -H "X-Api-Key: vf_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "user_image_b64": "data:image/jpeg;base64,/9j/4AAQ...",
    "category_id":    14,
    "collection_id":  "gid://shopify/Collection/289346731"
  }'

Mode 3 — Multipart/form-data (upload direct)

curl -X POST https://cabine.ai/api/v2/look-tryon \
  -H "X-Api-Key: vf_live_xxx" \
  -F "user_photo=@/chemin/client.jpg" \
  -F "category_id=14"

Réponse succès (200)

{
  "success": true,
  "selected_look": {
    "id":          42,
    "name":        "Urban Minimal Denim",
    "description": "Look casual minimal avec veste denim et pantalon beige.",
    "reason":      "Ce look fonctionne particulièrement bien avec votre carnation, les couleurs s'accordent à votre palette — un équilibre subtil pensé pour vous mettre en valeur.",
    "match_score": 0.78,
    "image_url":   "https://cdn.marque.com/looks/look-042.jpg",
    "tags": {
      "style":    ["casual", "minimal", "urban"],
      "occasion": ["daily", "weekend"],
      "season":   ["spring", "summer"],
      "colors":   ["navy blue", "beige", "white"]
    },
    "products": [
      {
        "name":        "Veste denim oversize",
        "product_url": "https://maboutique.com/p/veste-denim-oversize",
        "product_id":  "shopify_gid_xxx"
      },
      {
        "name":        "Pantalon droit beige",
        "product_url": "https://maboutique.com/p/pantalon-droit-beige",
        "product_id":  "shopify_gid_yyy"
      }
    ]
  },
  "alternatives": [
    {
      "id":          47,
      "name":        "Soft Cream Layering",
      "description": "Layering doux crème et beige.",
      "match_score": 0.71,
      "image_url":   "https://cdn.marque.com/looks/look-047.jpg",
      "tags":        { /* idem */ },
      "products":    [ /* idem */ ]
    },
    {
      "id":          53,
      "name":        "Workwear Heritage",
      "description": "Workwear chino et chambray.",
      "match_score": 0.68,
      "image_url":   "https://cdn.marque.com/looks/look-053.jpg",
      "tags":        { /* idem */ },
      "products":    [ /* idem */ ]
    }
  ],
  "tryon": {
    "status":    "completed",
    "image_url": "https://cabine.ai/api/v1/result/a3f8...b2"
  },
  "generation_id":      2087,
  "credits_used":       1,
  "credits_remaining":  161,
  "processing_time_ms": 12340
}

Réponse — génération encore en cours (202 Accepted)

La génération d'image est asynchrone (même infrastructure que /api/v1/generate). Si elle dépasse le délai d'attente synchrone, l'API répond 202 Accepted avec tryon.status = "pending" et une poll_url. Le matching et les recommandations (selected_look, alternatives) sont déjà disponibles ; seule l'image se fait attendre.

{
  "success": true,
  "selected_look": { /* … identique … */ },
  "alternatives":  [ /* … identique … */ ],
  "tryon": {
    "status":   "pending",
    "poll_url": "https://cabine.ai/api/v1/generation/2087/status"
  },
  "generation_id": 2087,
  "message":       "Génération en cours. Interrogez poll_url pour récupérer le résultat."
}
Le polling utilise le même endpoint que la V1 : GET /api/v1/generation/{id}/status. Quand status passe à success, récupérez result_url. Le crédit n'est débité qu'une fois — au lancement de la génération.

Champs de la réponse — niveau racine

ChampTypeDescription
successbooltrue si le pipeline (analyse + matching + lancement génération) a réussi
selected_lookobjectLook sélectionné par le matcher (voir détail ci-dessous)
alternativesarray2 Looks suivants du ranking (sans génération try-on). Permet d'afficher « Vous pourriez aussi aimer… » sans nouvel appel API.
tryonobjectRésultat de la génération : { status: "completed", image_url } si prête, ou { status: "pending", poll_url } si encore en cours
generation_idintID interne — à conserver pour le polling et le lien avec POST /conversion
credits_usedintToujours 1 pour cet endpoint (comme V1) — présent uniquement si status = completed
credits_remainingintCrédits restants sur l'abonnement — présent uniquement si status = completed
processing_time_msintDurée totale du pipeline en millisecondes — présent uniquement si status = completed

Champs du selected_look

ChampTypeDescription
idintID interne du Look
namestringNom du Look (court, évocateur)
descriptionstring|nullDescription marchande du Look (FR)
reasonstringJustification humaine en français : « ce look fonctionne avec votre carnation, les couleurs s'accordent à votre palette… ». À afficher au client comme « explication du personal shopper ».
match_scorefloatScore de matching (0.0 à 1.0). Sert au tri et à la transparence.
image_urlstringURL de l'image de référence du Look (telle que renseignée par la marque)
tagsobject{ style[], occasion[], season[], colors[] } — pour badges/filtres côté front
productsarrayListe des pièces du Look avec leur URL fiche produit cliquable et leur ID CMS. C'est le point de conversion.

Mode test

Avec une clé API en mode test (vf_test_xxx), l'endpoint retourne un placeholder en quelques centaines de millisecondes sans appel Gemini ni débit de crédits. La réponse expose is_test_mode: true pour permettre à votre intégration de l'identifier.

tryon.image_url est servi via la même infrastructure que les générations V1 (token sécurisé, durée de conservation alignée sur votre plan, expiration → HTTP 410). Cf. /api/v1/generate.

Créer des Looks V2

La création et la gestion des Looks se fait depuis le back-office Cabine.ai (pas via l'API). Chaque Look est :

  • Une tenue complète validée par la marque (image d'un mannequin / photo éditoriale / flatlay)
  • Rattaché à une catégorie Cabine.ai et optionnellement à une collection (ID libre côté CMS)
  • Décrit par un breakdown forensique de chaque pièce (couleur, matière, finition, hardware, branding…) généré automatiquement par Gemini à l'upload
  • Doté d'un prompt try-on dédié (structure rigoureuse mirror-style, verrouillage de l'identité utilisateur, fidélité 1:1 du produit) éditable par la marque
  • Doté de tags stylistiques (style, occasion, saison, couleurs) et de compatibilités cibles (carnation, cheveux, morphologie) pour le matcher
  • Associé à une liste de produits cliquables (nom + URL fiche produit + ID CMS)

Cycle de vie d'un Look

StatutMatchable par /look-tryon ?Description
draftnonLook en cours de validation marchande. N'apparaît pas dans les recommandations.
publishedouiValidé par la marque, visible et matchable par l'API V2.
archivednonRetiré du catalogue (collection passée, fin de stock). Conservé pour historique mais non recommandé.

Workflow recommandé en BO

  1. Aller dans Mon compte → Looks → « Nouveau Look »
  2. Upload de l'image du Look (JPEG · PNG · WebP, max 15 Mo)
  3. Cliquer « Analyser avec Gemini » : le formulaire se pré-remplit (nom, description, tags, targeting, pièces détectées, prompt try-on)
  4. Renseigner les URLs des fiches produit pour chaque pièce (point de conversion essentiel)
  5. Ajuster les tags/targeting/prompt si besoin
  6. « Publier » → le Look devient matchable par POST /api/v2/look-tryon
Création d'un Look en moins de 30 secondes grâce à l'analyse stylistique automatique de Gemini.

Bonnes pratiques pour la qualité du matching

  • Image du Look : mannequin de face, plein corps visible, fond uni ou éditorial clair, résolution ≥ 800 × 1066 px (ratio portrait 3:4 recommandé)
  • Tags stylistiques : remplissez systématiquement style, occasion, saison et couleurs — Gemini fait un bon premier jet, mais une revue humaine améliore significativement le matching
  • Targeting morphologique : laissez vide si le Look est universel ; ne remplissez que si une compatibilité est vraiment dominante (ex : robe ajustée → hourglass, rectangle)
  • URLs produit : renseignez-les toutes, même pour les accessoires — c'est ce qui transforme l'essayage en revenu
  • Catalogue minimum : visez 20+ Looks publiés couvrant 3-4 catégories pour que le matcher ait de la matière. En dessous, les résultats peuvent paraître répétitifs.

Codes d'erreur spécifiques V2 V2

L'endpoint POST /api/v2/look-tryon ajoute plusieurs codes spécifiques à son pipeline. Ils sont retournés avec leur code HTTP approprié et un message lisible en français.

HTTPCodeQuandAction recommandée
402 no_active_subscription Aucun abonnement actif sur le compte Souscrire un plan
404 no_looks_available Aucun Look publié pour le marchand (et/ou cette category_id/collection_id) Publier au moins un Look dans le BO ; vérifier les filtres envoyés
404 look_not_found look_id fourni mais introuvable, non publié, ou n'appartenant pas à ce compte Utiliser un id issu du bloc alternatives d'une réponse précédente
409 gender_mismatch look_id valide mais incompatible avec le genre détecté sur la photo Proposer un Look adapté au profil ; ce garde-fou est volontaire
422 invalid_param Aucune photo utilisateur fournie (ou format/encodage invalide) Vérifier que user_image_url, user_image_b64 ou user_photo est bien envoyé
422 invalid_category category_id fourni mais introuvable ou désactivée Omettre le paramètre ou utiliser un category_id valide
422 no_usable_look Le Look matché (et ses alternatives) n'ont pas de prompt try-on configuré Relancer l'analyse Gemini ou saisir manuellement le prompt depuis le BO
429 quota_exceeded Aucun crédit disponible Attendre le renouvellement ou upgrader le plan ; la réponse inclut needed et remaining
500 profile_analysis_failed L'analyse stylistique Gemini de la photo utilisateur a échoué (image illisible, contenu non analysable, surcharge Gemini) Réessayer avec une autre photo (face caméra, bonne luminosité, ≥ 400 × 400 px)
500 matching_failed Le matcher n'a pu sélectionner aucun Look (cas pathologique) Contacter le support — incident exceptionnel
500 generation_failed Échec de Gemini Image lors de la génération photoréaliste Réessayer après 5 s (max 3 tentatives) — aucun crédit n'est débité en cas d'échec

Exemple de réponse d'erreur — quota insuffisant

{
  "success":   false,
  "error":     "quota_exceeded",
  "message":   "Crédits insuffisants pour générer l'essayage.",
  "needed":    2,
  "remaining": 1
}

Intégration PrestaShop

Le module cabineai supporte nativement l'API cabine.ai en mode SaaS. Configurez votre clé API depuis Mon compte → Clés API.

Configuration du module

# BO PrestaShop → Modules → cabineai → Configurer
Mode          : SaaS (API externe)
API Endpoint  : https://cabine.ai/api/v1/generate
API Key       : vf_live_xxxxxxxx...   ← Depuis Mon compte → Clés API
Type de rendu : mirror | universe     ← Optionnel, active le prompt par catégorie

Flux complet recommandé

1. Client clique "Essayer ce vêtement" sur la fiche produit
2. Upload photo → module encode en base64
   POST /api/v1/generate avec :
     - product_id, cart_id, customer_id     (tracking)
     - category, product_name, prompt_type  (prompts intelligents)
3. API résout la catégorie → sélectionne le prompt adapté
4. API génère l'image (~15-90s selon le modèle)
5. API retourne result_url + generation_id → module affiche l'image
6. Client passe commande
7. Webhook PrestaShop → POST /api/v1/conversion avec order_id, product_id, cart_id
8. L'API relie automatiquement la commande à l'essayage d'origine

Appel génération — exemple PHP complet

// Dans le controller AJAX du module (controllers/front/ajax.php)
$product      = new Product((int) Tools::getValue('id_product'));
$category     = new Category($product->id_category_default, Context::getContext()->language->id);

$payload = json_encode([
    'product_image_b64' => 'data:image/jpeg;base64,' . base64_encode(file_get_contents($productImagePath)),
    'user_photo_b64'    => 'data:image/jpeg;base64,' . base64_encode(file_get_contents($userPhotoTmpPath)),
    // Prompts intelligents (optionnels — ignorés si aucun match)
    'category'          => $category->name,
    'product_name'      => $product->name[Context::getContext()->language->id],
    'prompt_type'       => Configuration::get('CABINEAI_PROMPT_TYPE', 'mirror'),
    // Tracking (recommandé)
    'product_id'        => (int) Tools::getValue('id_product'),
    'cart_id'           => (int) Context::getContext()->cart->id,
    'customer_id'       => (int) Context::getContext()->customer->id, // 0 si visiteur
]);

$response = file_get_contents('https://cabine.ai/api/v1/generate', false,
    stream_context_create(['http' => [
        'method'  => 'POST',
        'header'  => "X-Api-Key: vf_live_xxx\r\nContent-Type: application/json",
        'content' => $payload,
        'timeout' => 120,
        'ignore_errors' => true,
    ]])
);

$data = json_decode($response, true);
if ($data['success']) {
    $resultUrl    = $data['result_url'];
    $generationId = $data['generation_id'];
}
Pourquoi base64 et non URL ? Votre boutique PrestaShop peut être en local, staging ou derrière un VPN — le serveur cabine.ai ne pourrait pas accéder à une URL interne. Le base64 encode l'image directement dans la requête et fonctionne dans tous les environnements.

Modèle de crédits

V1 : 1 essayage = 1 crédit, quel que soit le modèle et le type de prompt.
V2 : 1 appel /look-tryon = 1 crédit (identique à un essayage V1 ; analyse et matching offerts).
Modèle par défaut : gemini-3-pro-image-preview.

Les crédits sont renouvelés le 1er de chaque mois. Les crédits non utilisés ne sont pas reportés. Les crédits bonus (ajoutés manuellement par le support) s'ajoutent aux crédits du plan et sont inclus dans credits_remaining. Aucun crédit n'est débité en cas d'échec du pipeline (transactionnel).

Bonnes pratiques

Génération V1 — Essayage produit unique

  • Images produit : fond blanc ou uni, vêtement visible en entier, résolution ≥ 800 px
  • Photos utilisateur : portrait face caméra, haut du corps visible, bonne luminosité, résolution ≥ 400 × 400 px
  • Timeout client : prévoyez 120 s — la génération peut prendre jusqu'à 90 s selon la charge
  • Prompts intelligents : envoyez toujours category + product_name + prompt_type pour bénéficier des prompts optimisés par catégorie
  • Tracking : passez toujours product_id et cart_id pour activer le lien automatique avec les conversions

Look Try-On V2 — Personal shopper

  • Photo utilisateur : plein corps si possible (le matcher exploite la morphologie), face caméra, bonne luminosité, ≥ 600 × 800 px
  • Timeout client : prévoyez 180 s — le pipeline complet (analyse + matching + génération) est plus long que V1
  • Catalogue Looks : visez 20+ Looks publiés pour un matching pertinent ; couvrez plusieurs catégories pour ne pas avoir de bruit dans les recommandations
  • Filtres : n'utilisez category_id/collection_id que si vous avez une intention claire (page collection, contexte saisonnier) — sinon laissez l'IA choisir parmi tous les Looks
  • Affichage côté front : exploitez selected_look.reason tel quel pour créer un effet « personal shopper » authentique ; affichez les alternatives sous l'image principale pour augmenter le panier moyen
  • Conversion : les selected_look.products[].product_url sont vos boutons « Acheter cette pièce » ; trackez les clics pour mesurer le taux de transformation par Look

Commun aux deux versions

  • Conversions : appelez POST /conversion depuis un hook de confirmation de commande, avec un timeout court et ignore_errors: true pour ne pas bloquer la boutique
  • Stockage : sauvegardez result_url / tryon.image_url en base de données — les fichiers sont conservés 4 minutes puis supprimés directement (sauf la génération d'un essayage partagée par l'utilisateur)
  • Quota : vérifiez GET /quota avant un batch pour anticiper les erreurs 429 ; V1 et V2 consomment 1 crédit par appel
  • Retry : en cas d'erreur 500, attendez 5 s avant de réessayer (max 3 tentatives) — aucun crédit n'est débité tant qu'aucune réponse 200 n'a été retournée

Des questions ? support@cabine.ai

Créer un compte gratuit →