ULTINEO

Catalogue

Votre catalogue existe souvent déjà ailleurs — un ERP, un fichier fournisseur, une ancienne boutique. Les points d'accès du catalogue permettent à vos outils de l'envoyer à votre boutique par lots et de relire chaque enregistrement : les caractéristiques (comme la capacité ou la couleur) et leurs valeurs, les catégories, les groupes de produits avec leurs sélecteurs, les produits avec leurs niveaux d'état, leurs caractéristiques et leurs photos, ainsi que l'historique des avis clients.

Chaque import suit le contrat commun décrit dans Votre premier appel : une liste items, un dry_run facultatif et un rapport ligne par ligne.

Points d'accès

MéthodeCheminDroitLimite par lot
POST/v1/attribute/importattribute:write25 caractéristiques, 400 valeurs chacune
GET/v1/attribute/importattribute:readUne caractéristique
POST/v1/category/importcategory:write50 catégories
GET/v1/category/importcategory:readUne catégorie
POST/v1/product-group/importproduct_group:write50 groupes, 20 axes chacun
GET/v1/product-group/importproduct_group:readUn groupe
POST/v1/product/importproduct:write40 produits
GET/v1/product/importproduct:readUn produit
POST/v1/product-review/importproduct_review:write250 avis clients
GET/v1/product-review/importproduct_review:readUn avis client

Importez dans cet ordre, car chaque enregistrement fait référence aux précédents : les caractéristiques, puis les catégories, puis les groupes de produits, puis les produits, puis les avis clients. Les avis clients font aussi référence aux clients et aux commandes, importés via Commandes & logistique.

Comment les enregistrements du catalogue sont reconnus

RessourceReconnue parRenvoyé dans l'external_id du rapport
Caractéristiquename, sans tenir compte de la casseLe nom
Catégoriename, sans tenir compte de la casseLe nom
Groupe de produitsnameLe nom
ProduitskuLe SKU
Avis clientexternal_idL'external_id de l'avis client

Comme le nom est la clé d'une caractéristique, d'une catégorie ou d'un groupe, envoyer un nouveau nom crée un nouvel enregistrement au lieu de renommer l'ancien.

Lorsqu'un élément porte une liste enfant — les values d'une caractéristique, les axes d'un groupe, les grades ou les media d'un produit — cette liste constitue l'ensemble complet : les entrées manquantes sont ajoutées, celles qui ont changé sont corrigées et celles que vous avez omises sont désactivées. Omettez la liste pour conserver l'ensemble enregistré tel quel.

Caractéristiques

Une caractéristique décrit des produits, comme Capacité ou Couleur, et peut porter une liste fermée de valeurs (64 Go, 128 Go). Votre boutique peut aussi lire les caractéristiques partagées par le service ; elles sont renvoyées avec "shared": true et ne peuvent pas être modifiées.

Importer des caractéristiques

POST /v1/attribute/import

ChampTypeObligatoireDescription
namechaîneOui, sauf pour colourJusqu'à 190 octets. Une caractéristique colour s'appelle toujours Colour.
kindchaîneNoncustom (par défaut) ou colour. Le type d'une caractéristique existante n'est jamais modifié.
unitchaîneNonJusqu'à 30 octets, comme GB. Caractéristiques custom uniquement.
scopechaîneNoncatalog (par défaut), category ou product.
scope_identchaîneLorsque scope n'est pas catalogL'identifiant de la catégorie ou du produit auquel s'applique la caractéristique.
positionentierNonOrdre d'affichage.
statuschaîneNonactivated (par défaut) ou suspended.
valuestableauNonLa liste complète des valeurs (voir ci-dessous).

Chaque entrée de values :

ChampTypeObligatoireDescription
labelchaîneOuiJusqu'à 190 octets, unique dans la caractéristique sans tenir compte de la casse.
hexchaînePour colour uniquementUn code couleur de six chiffres hexadécimaux, avec ou sans #. Refusé sur une caractéristique custom.
positionentierNonOrdre d'affichage. S'il est omis, la valeur se place en dernier.
statuschaîneNonactivated ou suspended.
descriptionchaîneNonUne remarque sur la valeur, jusqu'à 500 caractères.
link_labelchaîneNonLe texte d'un lien affiché avec la remarque. Envoyez-le avec link_page.
link_pagechaîneNonL'identifiant de l'une des pages de texte de votre boutique qu'ouvre le lien. Envoyez '' avec link_label: '' pour supprimer le lien.
curl
curl https://api.ultineo.com/v1/attribute/import \
  -H "Authorization: Bearer sk-project-YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      {
        "name": "Capacity",
        "unit": "GB",
        "values": [
          { "label": "64 GB", "position": 1 },
          { "label": "128 GB", "position": 2 }
        ]
      },
      {
        "kind": "colour",
        "values": [
          { "label": "Midnight", "hex": "#1c1c28" },
          { "label": "Starlight", "hex": "f4efe6" }
        ]
      }
    ]
  }'
application/json
{
  "code": 200,
  "title": "OK",
  "response": {
    "object": "list",
    "resource": "attribute",
    "dry_run": false,
    "data": [
      { "index": 0, "external_id": "Capacity", "action": "created", "id": "attr_9e2f41c07a3b5d8e6f10", "code": null, "title": null, "reason": null, "notice": [] },
      { "index": 1, "external_id": "Colour", "action": "updated", "id": "attr_3a7c0d95e1f24b6a8c52", "code": null, "title": null, "reason": null, "notice": [] }
    ],
    "created": 1,
    "updated": 1,
    "unchanged": 0,
    "refused": 0,
    "total": 2
  }
}

Lire une caractéristique

GET /v1/attribute/import

ParamètreEmplacementDescription
namequeryLe nom de la caractéristique. Prioritaire sur id.
idquerySon identifiant, préfixé par attr_.

Sans l'un ni l'autre, l'appel répond 400 Missing required parameter: name. ; une caractéristique inconnue répond 404 Characteristic not found.

curl
curl "https://api.ultineo.com/v1/attribute/import?name=Capacity" \
  -H "Authorization: Bearer sk-project-YOUR_KEY"
application/json
{
  "code": 200,
  "title": "OK",
  "response": {
    "object": "attribute",
    "id": "attr_9e2f41c07a3b5d8e6f10",
    "name": "Capacity",
    "kind": "custom",
    "unit": "GB",
    "scope": "catalog",
    "scope_ident": "",
    "position": 0,
    "status": "activated",
    "shared": false,
    "values": [
      { "id": "atvl_51d0e8a3c7b2f49e6a01", "label": "64 GB", "hex": "", "position": 1, "status": "activated", "description": "", "link_label": "", "link_page": "" },
      { "id": "atvl_c48b2e7f90a1d35e6b72", "label": "128 GB", "hex": "", "position": 2, "status": "activated", "description": "", "link_label": "", "link_page": "" }
    ],
    "created_at": 1789143990,
    "updated_at": 1789143990
  }
}

Seules les valeurs actives sont renvoyées, dans l'ordre d'affichage.

Catégories

Une catégorie est un rayon de votre catalogue ; les catégories s'imbriquent via parent.

Importer des catégories

POST /v1/category/import

ChampTypeObligatoireDescription
namechaîneOuiJusqu'à 190 octets.
parentchaîneNonLa catégorie parente, par identifiant (cate_…) ou par nom. '' en fait une catégorie de premier niveau. Un parent qui ferait de la catégorie son propre ancêtre est refusé.
descriptionchaîneNonLa description de la catégorie.
imagechaîneNonL'identifiant d'une image déjà présente dans vos médias.
positionentierNonOrdre d'affichage.
statuschaîneNonactivated (par défaut) ou suspended.
slugchaîneNonLe segment d'adresse. Généré à partir du nom s'il est laissé vide.
seo_titlechaîneNonJusqu'à 190 octets.
seo_descriptionchaîneNonLa description destinée aux moteurs de recherche.
seo_imagechaîneNonL'identifiant de l'image partagée sur les réseaux sociaux.
referencechaîneNonVotre propre référence, jusqu'à 190 octets.
warrantychaîneNonL'identifiant d'une garantie de votre boutique.

Envoyez les parents avant leurs enfants, dans le même lot ou dans un lot précédent.

curl
curl https://api.ultineo.com/v1/category/import \
  -H "Authorization: Bearer sk-project-YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "dry_run": true,
    "items": [
      { "name": "Smartphones", "description": "Refurbished smartphones, tested and graded.", "position": 1 },
      { "name": "iPhone", "parent": "Smartphones", "position": 1 }
    ]
  }'
application/json
{
  "code": 200,
  "title": "OK",
  "response": {
    "object": "list",
    "resource": "category",
    "dry_run": true,
    "data": [
      { "index": 0, "external_id": "Smartphones", "action": "unchanged", "id": "cate_4be1a07f93c2d58e6a10", "code": null, "title": null, "reason": null, "notice": [] },
      { "index": 1, "external_id": "iPhone", "action": "created", "id": null, "code": null, "title": null, "reason": null, "notice": [] }
    ],
    "created": 1,
    "updated": 0,
    "unchanged": 1,
    "refused": 0,
    "total": 2
  }
}

Lire une catégorie

GET /v1/category/import

ParamètreEmplacementDescription
namequeryLe nom de la catégorie. Prioritaire sur id.
idquerySon identifiant, préfixé par cate_.

Sans l'un ni l'autre, l'appel répond 400 Missing required parameter: name. ; une catégorie inconnue répond 404 Category not found. La requête et la réponse complètes figurent dans Votre premier appel.

Groupes de produits

Un groupe de produits rassemble les variantes d'un même produit — par exemple toutes les capacités et couleurs d'un modèle de téléphone — et définit les axes parmi lesquels l'acheteur choisit sur la fiche produit. Un produit rejoint un groupe via son champ group.

Importer des groupes de produits

POST /v1/product-group/import

ChampTypeObligatoireDescription
namechaîneOuiJusqu'à 190 octets.
statuschaîneNonactivated (par défaut) ou suspended.
axestableauNonLa liste complète des axes, jusqu'à 20 (voir ci-dessous).

Chaque entrée de axes :

ChampTypeObligatoireDescription
sourcechaîneNoncharacteristic (par défaut), grade ou custom.
attributechaîneLorsque source vaut characteristicLa caractéristique proposée par l'axe, par identifiant ou par nom. Refusé pour les autres sources.
namechaîneLorsque source vaut customLe libellé de l'axe, jusqu'à 190 octets.
kindchaîneNonLa manière dont les options sont affichées : pill (par défaut), swatch, card ou list. Un axe grade est card ou list.
price_modechaîneNonprice, from, diff, none, ou '' pour la valeur par défaut. Les axes pill et swatch n'acceptent que none ; un axe grade n'accepte pas from.
positionentierNonOrdre d'affichage. S'il est omis, l'axe se place en dernier.
statuschaîneNonactivated ou suspended.

Un axe est reconnu par ce qu'il propose : sa caractéristique, le niveau d'état (au plus un axe de niveau d'état par groupe) ou, pour un axe personnalisé, son nom.

curl
curl https://api.ultineo.com/v1/product-group/import \
  -H "Authorization: Bearer sk-project-YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      {
        "name": "iPhone 13",
        "axes": [
          { "source": "characteristic", "attribute": "Capacity", "kind": "pill", "position": 1 },
          { "source": "characteristic", "attribute": "Colour", "kind": "swatch", "position": 2 },
          { "source": "grade", "kind": "card", "price_mode": "price", "position": 3 }
        ]
      }
    ]
  }'
application/json
{
  "code": 200,
  "title": "OK",
  "response": {
    "object": "list",
    "resource": "product_group",
    "dry_run": false,
    "data": [
      { "index": 0, "external_id": "iPhone 13", "action": "created", "id": "prgr_06b3e9d2a4c71f58e0b9", "code": null, "title": null, "reason": null, "notice": [] }
    ],
    "created": 1,
    "updated": 0,
    "unchanged": 0,
    "refused": 0,
    "total": 1
  }
}

Lire un groupe de produits

GET /v1/product-group/import

ParamètreEmplacementDescription
namequeryLe nom du groupe. Prioritaire sur id.
idquerySon identifiant, préfixé par prgr_.

Sans l'un ni l'autre, l'appel répond 400 Missing required parameter: name. ; un groupe inconnu répond 404 Product group not found.

curl
curl "https://api.ultineo.com/v1/product-group/import?name=iPhone%2013" \
  -H "Authorization: Bearer sk-project-YOUR_KEY"
application/json
{
  "code": 200,
  "title": "OK",
  "response": {
    "object": "product_group",
    "id": "prgr_06b3e9d2a4c71f58e0b9",
    "name": "iPhone 13",
    "status": "activated",
    "axes": [
      { "id": "pgax_7f1e0c39b52a4d86e3a1", "name": "", "kind": "pill", "source": "characteristic", "attribute": "attr_9e2f41c07a3b5d8e6f10", "price_mode": "", "position": 1, "status": "activated" },
      { "id": "pgax_b2d84a61f0e9c357a1d4", "name": "", "kind": "swatch", "source": "characteristic", "attribute": "attr_3a7c0d95e1f24b6a8c52", "price_mode": "", "position": 2, "status": "activated" },
      { "id": "pgax_e05c7b3a9d1f6248b0c6", "name": "", "kind": "card", "source": "grade", "attribute": "", "price_mode": "price", "position": 3, "status": "activated" }
    ],
    "created_at": 1789144034,
    "updated_at": 1789144034
  }
}

Produits

Un produit est un article vendable, reconnu par son SKU. Il peut porter des niveaux d'état (chacun avec son propre prix et son propre stock), des caractéristiques et des photos déjà téléversées dans vos médias.

Importer des produits

POST /v1/product/import

ChampTypeObligatoireDescription
skuchaîneOuiVotre SKU, jusqu'à 190 octets. external_id est accepté comme alias.
currencychaînePour un nouveau produitLa devise de tous les prix du produit, comme EUR.
namechaîneNonJusqu'à 190 octets. Par défaut, le SKU.
descriptionchaîneNonLa description du produit.
eanchaîneNonLe code-barres.
statuschaîneNondraft (par défaut), activated ou suspended.
categorychaîneNonL'identifiant d'une catégorie de votre boutique (cate_…).
groupchaîneNonL'identifiant d'un groupe de produits de votre boutique (prgr_…).
brandchaîneNonL'identifiant d'une marque de votre boutique.
warrantychaîneNonL'identifiant d'une garantie de votre boutique.
conditionchaîneNonUn court libellé d'état, jusqu'à 20 octets.
pricenombre ou chaîneNonZéro ou plus, avec jusqu'à 2 décimales.
price_comparenombre ou chaîneNonLe prix de référence affiché barré, même format.
weightnombre ou chaîneNonZéro ou plus, avec jusqu'à 3 décimales.
stockentierNonUnités en stock.
stock_thresholdentierNonLe seuil d'alerte de stock bas.
slugchaîneNonLe segment d'adresse. Généré à partir du nom s'il est laissé vide.
seo_titlechaîneNonJusqu'à 190 octets.
seo_descriptionchaîneNonLa description destinée aux moteurs de recherche.
seo_imagechaîneNonL'identifiant de l'image partagée sur les réseaux sociaux.
badgechaîneNonLes badges du produit.
tagchaîneNonLes étiquettes du produit.
notechaîneNonUne note interne.
created_atentierNonLa date de création d'origine, en secondes Unix. Conservée à la création et jamais modifiée par un import ultérieur.
gradestableauNonLa liste complète des niveaux d'état (voir ci-dessous).
attributestableauNonLes valeurs de caractéristiques (voir ci-dessous).
mediatableauNonLa liste complète des photos (voir ci-dessous).

Chaque entrée de grades :

ChampTypeObligatoireDescription
gradechaîneOuinew, like_new, very_good, good ou poor, une seule fois chacun.
pricenombre ou chaîneNonLe prix du niveau d'état.
stockentierNonLe stock du niveau d'état.
statuschaîneNonactivated (par défaut) ou suspended.

Lorsqu'un produit a des niveaux d'état, son price est le prix le plus bas parmi ses niveaux d'état et son stock est la somme de leurs stocks ; un price ou un stock de premier niveau que vous envoyez n'est alors pas appliqué, et un notice le signale.

Chaque entrée de attributes :

ChampTypeObligatoireDescription
typechaîneOuiLa caractéristique, par identifiant ou par nom.
valuechaîneOuiLa valeur, jusqu'à 190 octets. Lorsque la caractéristique a une liste de valeurs, elle doit en faire partie.
unitchaîneNonUne unité, jusqu'à 50 octets.
positionentierNonOrdre d'affichage.

Seules les caractéristiques nommées dans attributes sont mises à jour ; les autres caractéristiques du produit sont conservées.

Chaque entrée de media :

ChampTypeObligatoireDescription
filechaîneOuiL'identifiant d'un fichier déjà téléversé dans vos médias.
is_mainbooléenNontrue pour la photo de couverture ; une au plus par produit.
positionentierNonOrdre d'affichage. Par défaut, l'ordre de la liste.

Remarque — L'API associe des photos déjà présentes dans vos médias ; elle ne téléverse pas de fichiers. Un produit supprimé conserve son statut : un import ne le restaure jamais.

curl
curl https://api.ultineo.com/v1/product/import \
  -H "Authorization: Bearer sk-project-YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      {
        "sku": "IP13-128-MID",
        "name": "iPhone 13 128 GB Midnight",
        "currency": "EUR",
        "status": "activated",
        "category": "cate_4be1a07f93c2d58e6a10",
        "group": "prgr_06b3e9d2a4c71f58e0b9",
        "price_compare": "729.00",
        "weight": 0.174,
        "grades": [
          { "grade": "very_good", "price": 459.00, "stock": 6 },
          { "grade": "good", "price": 419.00, "stock": 3 }
        ],
        "attributes": [
          { "type": "Capacity", "value": "128 GB" },
          { "type": "Colour", "value": "Midnight" }
        ],
        "media": [
          { "file": "file_2c7e91a0d4b3f56e8a17", "is_main": true }
        ]
      }
    ]
  }'
application/json
{
  "code": 200,
  "title": "OK",
  "response": {
    "object": "list",
    "resource": "product",
    "dry_run": false,
    "data": [
      { "index": 0, "external_id": "IP13-128-MID", "action": "created", "id": "prod_a81f3c6e0b2d49e7c5f0", "code": null, "title": null, "reason": null, "notice": [] }
    ],
    "created": 1,
    "updated": 0,
    "unchanged": 0,
    "refused": 0,
    "total": 1
  }
}

Remarque — En mode essai, les champs propres au produit sont comparés à ce qui est enregistré ; ses grades, attributes et media sont vérifiés mais pas comparés.

Lire un produit

GET /v1/product/import

ParamètreEmplacementDescription
skuqueryLe SKU du produit (external_id est accepté comme alias). Prioritaire sur id.
idquerySon identifiant, préfixé par prod_.

Sans l'un ni l'autre, l'appel répond 400 Missing required parameter: sku. ; un produit inconnu répond 404 Product not found. Un produit supprimé dans votre espace de travail est tout de même renvoyé, avec "status": "deleted".

curl
curl "https://api.ultineo.com/v1/product/import?sku=IP13-128-MID" \
  -H "Authorization: Bearer sk-project-YOUR_KEY"
application/json
{
  "code": 200,
  "title": "OK",
  "response": {
    "object": "product",
    "id": "prod_a81f3c6e0b2d49e7c5f0",
    "sku": "IP13-128-MID",
    "status": "activated",
    "name": "iPhone 13 128 GB Midnight",
    "description": "",
    "ean": "",
    "category": "cate_4be1a07f93c2d58e6a10",
    "group": "prgr_06b3e9d2a4c71f58e0b9",
    "brand": "",
    "warranty": "",
    "condition": "",
    "price": "419.00",
    "price_compare": "729.00",
    "currency": "EUR",
    "weight": "0.174",
    "stock": 9,
    "stock_threshold": 0,
    "slug": "iphone-13-128-gb-midnight-1842",
    "seo_title": "",
    "seo_description": "",
    "seo_image": "",
    "badge": "",
    "tag": "",
    "note": "",
    "created_at": 1789144100,
    "updated_at": 1789144100
  }
}

La lecture renvoie les champs propres au produit ; ses niveaux d'état, ses caractéristiques et ses photos ne font pas partie de la réponse.

Avis clients

Un avis client est une note et un commentaire laissés par un client sur un produit. Importez l'historique des avis clients de votre ancienne boutique, rattachés au client et, le cas échéant, à la commande dont ils proviennent.

Importer des avis clients

POST /v1/product-review/import

ChampTypeObligatoireDescription
external_idchaîneOuiVotre référence pour l'avis client, jusqu'à 50 caractères, unique dans le lot.
customer_external_idchaîneOuiL'external_id d'un client déjà importé.
product_skuchaîneOuiLe SKU du produit évalué. Un SKU qui n'est pas encore dans votre catalogue est accepté et l'avis client est conservé avec le SKU seul ; un notice le signale.
ratingentierOuiUn nombre entier de 1 à 5.
order_external_idchaîneNonL'external_id d'une commande déjà importée. Une commande indiquée qui n'existe pas entraîne le refus de l'avis client.
order_item_external_idchaîneNonL'external_id d'une ligne de cette commande. Nécessite order_external_id.
namechaîneNonLe nom affiché de l'auteur de l'avis, jusqu'à 50 caractères.
textchaîneNonLe texte de l'avis client.
langchaîneNonLa langue sous forme de code ISO 639-3 à trois lettres, comme fra ou eng.
statuschaîneNonpending (par défaut pour un nouvel avis client), published ou rejected. deleted retire un avis client déjà importé.
created_atentierNonLa date d'origine, en secondes Unix. Si elle est omise, la date de la commande est utilisée. Jamais modifiée par un import ultérieur.
curl
curl https://api.ultineo.com/v1/product-review/import \
  -H "Authorization: Bearer sk-project-YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      {
        "external_id": "REV-88412",
        "customer_external_id": "C1001",
        "order_external_id": "ORD-10458",
        "product_sku": "IP13-128-MID",
        "rating": 5,
        "name": "Claire M.",
        "text": "As good as new, battery at 92%.",
        "lang": "eng",
        "status": "published",
        "created_at": 1781517600
      }
    ]
  }'
application/json
{
  "code": 200,
  "title": "OK",
  "response": {
    "object": "list",
    "resource": "product_review",
    "dry_run": false,
    "data": [
      { "index": 0, "external_id": "REV-88412", "action": "created", "id": "prvw_f3a90b1d6c2e47e85a03", "code": null, "title": null, "reason": null, "notice": [] }
    ],
    "created": 1,
    "updated": 0,
    "unchanged": 0,
    "refused": 0,
    "total": 1
  }
}

Lire un avis client

GET /v1/product-review/import

ParamètreEmplacementDescription
external_idqueryLa référence de l'avis client dans votre ancien système. Prioritaire sur id.
idquerySon identifiant, préfixé par prvw_.

Sans l'un ni l'autre, l'appel répond 400 Missing required parameter: external_id. ; un avis client inconnu répond 404 Product review not found. Un avis client retiré est tout de même renvoyé, avec "status": "deleted".

curl
curl "https://api.ultineo.com/v1/product-review/import?external_id=REV-88412" \
  -H "Authorization: Bearer sk-project-YOUR_KEY"
application/json
{
  "code": 200,
  "title": "OK",
  "response": {
    "id": "prvw_f3a90b1d6c2e47e85a03",
    "object": "product_review",
    "external_id": "REV-88412",
    "status": "published",
    "customer": "cust_c3e9a1074b5d28f6e0a7",
    "order": "ordr_5e0a8c2f71d94b36e1c8",
    "order_item": "",
    "product": "prod_a81f3c6e0b2d49e7c5f0",
    "product_sku": "IP13-128-MID",
    "name": "Claire M.",
    "rating": 5,
    "text": "As good as new, battery at 92%.",
    "lang": "eng",
    "created_at": 1781517600,
    "updated_at": 1791745200
  }
}

customer, order, order_item et product sont des identifiants de votre boutique ; order, order_item et product sont vides lorsque l'avis client n'y est pas rattaché.

Remarque — Les points d'accès du catalogue ne listent, ne recherchent ni ne suppriment d'enregistrements. Les marques et les garanties sont créées dans votre espace de travail et sont seulement référencées ici, et les mouvements de stock restent dans votre espace de travail.