Votre premier appel
L'API Ultineo permet à vos propres outils de remplir votre boutique et de la relire : un script de migration, une synchronisation avec votre ERP ou un flux fournisseur envoie des éléments par lots, et relit n'importe quel élément pour vérifier ce qui a été enregistré. C'est une API JSON sur HTTPS. Vous vous authentifiez avec la clé API de votre boutique, vous appelez un chemin sous /v1/ et vous lisez le résultat dans une enveloppe de réponse unique.
Avant de commencer — Il vous faut une clé API pour votre boutique (elle commence par
sk-project-) détenant les droits de lecture et/ou d'écriture des ressources que vous appelez, ainsi qu'un moyen d'envoyer une requête HTTP avec un corps JSON, par exemplecurl.
URL de base
Toutes les requêtes sont envoyées à :
https://api.ultineo.com/v1/ Seul HTTPS est servi. Une requête sur http:// reçoit une redirection 301 vers le même chemin en https://.
Important — Votre clé circule dans un en-tête de requête : une seule requête en clair la divulgue en entier. Appelez toujours directement l'adresse
https://au lieu de compter sur la redirection.
Un point d'accès ne demande aucune clé ; vous pouvez l'utiliser pour vérifier que l'hôte est joignable :
curl https://api.ultineo.com/health {
"code": 200,
"title": "OK",
"response": "api gateway"
} Authentification
Envoyez votre clé comme jeton Bearer à chaque appel :
| En-tête | Valeur |
|---|---|
Authorization | Bearer sk-project-… |
Content-Type | application/json (uniquement lorsque vous envoyez un corps) |
Une clé appartient à une seule boutique. Chaque lecture et chaque écriture est limitée à cette boutique, quoi que vous mettiez dans l'URL ou dans le corps : un élément d'une autre boutique répond 404, exactement comme un élément qui n'existe pas. Une clé peut aussi être désactivée ou porter une date d'expiration ; une clé désactivée ou expirée est refusée (voir Codes d'erreur).
Droits
Chaque ressource a un droit (scope) de lecture et un droit d'écriture. Un GET exige le droit :read de la ressource et un POST exige son droit :write.
| Ressource | Droit de lecture | Droit d'écriture |
|---|---|---|
| Caractéristiques | attribute:read | attribute:write |
| Catégories | category:read | category:write |
| Groupes de produits | product_group:read | product_group:write |
| Produits | product:read | product:write |
| Avis produits | product_review:read | product_review:write |
| Clients | customer:read | customer:write |
| Commandes | order:read | order:write |
| Paiements | payment:read | payment:write |
| Expéditions | shipment:read | shipment:write |
| Réclamations transporteur | shipment_claim:read | shipment_claim:write |
| Colis refusés | shipment_refused:read | shipment_refused:write |
| Remboursements | refund:read | refund:write |
| Retours de commande | order_return:read | order_return:write |
| Portefeuille client | customer_wallet:read | customer_wallet:write |
| Demandes d'assistance | support_request:read | support_request:write |
| Bons de réduction | promotion:read | promotion:write |
Une clé peut aussi détenir <resource>:*, qui accorde les deux actions sur cette ressource, ou *, qui accorde tout. Un appel auquel il manque son droit est refusé avec 403 et un message nommant le droit manquant.
Remarque — Les bons de réduction utilisent les droits
promotion:readetpromotion:write, bien que leur chemin soit/v1/voucher/import.
Effectuer l'appel
Cet appel relit une catégorie de votre boutique par son nom :
curl "https://api.ultineo.com/v1/category/import?name=Smartphones" \
-H "Authorization: Bearer sk-project-YOUR_KEY" {
"code": 200,
"title": "OK",
"response": {
"object": "category",
"id": "cate_4be1a07f93c2d58e6a10",
"name": "Smartphones",
"slug": "smartphones-cate_4be1a07f93c2d58e6a10",
"description": "Refurbished smartphones, tested and graded.",
"parent": "",
"image": "",
"position": 1,
"status": "activated",
"seo_title": "",
"seo_description": "",
"seo_image": "",
"reference": "",
"warranty": "",
"created_at": 1789143990,
"updated_at": 1789143990
}
} L'enveloppe de réponse
Chaque point d'accès répond avec les trois mêmes clés, en cas de succès comme en cas d'échec. Lisez d'abord le code de statut HTTP, puis lisez response.
| Champ | Type | Description |
|---|---|---|
code | entier | Le code de statut HTTP, répété dans le corps. |
title | chaîne | Le libellé court du statut, par exemple OK ou Not Found. |
response | objet ou chaîne | L'élément ou le rapport d'import en cas de succès ; un message explicatif en cas d'échec. |
Fonctionnement de chaque import
Chaque ressource s'écrit selon le même contrat POST : dès que vous avez importé une ressource, vous savez les importer toutes.
Le corps de la requête
{
"dry_run": true,
"items": [
{ "name": "Smartphones" },
{ "name": "Tablets" }
]
} | Champ | Type | Obligatoire | Description |
|---|---|---|---|
items | tableau | Oui | Les éléments à importer, un objet chacun. Ce doit être une liste non vide, sans dépasser la limite de lot de la ressource. |
dry_run | booléen | Non | true vérifie tout le lot et indique ce qui se passerait, sans rien enregistrer. Vaut false par défaut. |
Le corps doit être un JSON valide et ne pas dépasser 200 000 octets. Chaque ressource a sa propre limite de lot, de 25 à 500 éléments, indiquée dans son tableau de points d'accès. Les ensembles plus grands s'envoient en plusieurs lots.
Renvoyer sans créer de doublons
Chaque élément est reconnu par sa propre clé — sa référence d'origine dans votre ancien système (external_id), ou son SKU ou son nom pour le catalogue. Envoyer un élément déjà présent dans votre boutique le met à jour si quelque chose a changé, ou le signale comme unchanged ; il n'est jamais créé deux fois. Vous pouvez donc rejouer un import interrompu depuis le début. Une mise à jour ne modifie que les champs que vous avez envoyés ; les champs omis gardent leur valeur enregistrée.
Tester avec le mode essai
Avec "dry_run": true, vous obtenez le rapport complet — ce qui serait créé, mis à jour, laissé inchangé ou refusé — et rien n'est écrit. Vérifiez toujours le champ dry_run de la réponse avant de vous fier à un rapport.
Le rapport d'import
{
"code": 200,
"title": "OK",
"response": {
"object": "list",
"resource": "category",
"dry_run": false,
"data": [
{
"index": 0,
"external_id": "Smartphones",
"action": "updated",
"id": "cate_4be1a07f93c2d58e6a10",
"code": null,
"title": null,
"reason": null,
"notice": []
},
{
"index": 1,
"external_id": "Tablets",
"action": "refused",
"id": null,
"code": 422,
"title": "Unprocessable Entity",
"reason": "status must be one of: activated, suspended.",
"notice": []
}
],
"created": 0,
"updated": 1,
"unchanged": 0,
"refused": 1,
"total": 2
}
} data contient une entrée par élément, dans l'ordre où vous les avez envoyés :
| Champ | Type | Description |
|---|---|---|
index | entier | La position de l'élément dans votre tableau items, à partir de 0. |
external_id | chaîne ou null | La clé par laquelle l'élément a été reconnu. |
action | chaîne | created, updated, unchanged ou refused. |
id | chaîne ou null | L'identifiant de l'élément dans votre boutique. null en cas de refus, et pour une création en mode essai. |
code | entier ou null | Pour un élément refusé, le code de statut du refus. |
title | chaîne ou null | Pour un élément refusé, le libellé de statut du refus. |
reason | chaîne ou null | Pour un élément refusé, ce qu'il faut corriger. |
notice | tableau | Messages d'information sur un élément accepté, par exemple une valeur qui a été ajustée. |
Les compteurs created, updated, unchanged et refused totalisent total, le nombre d'éléments que vous avez envoyés. Un élément refusé ne bloque jamais les autres : l'appel répond 200 dès qu'au moins un élément a été accepté, et 422 uniquement lorsque tous les éléments ont été refusés. Lisez donc le rapport ligne par ligne, même sur un 200.
Certaines ressources ajoutent leurs propres champs à chaque entrée, comme les lignes d'une commande ou les codes d'un bon de réduction ; ils sont décrits dans la rubrique de chaque ressource.
Relire un élément
Chaque ressource relit UN élément à la fois avec un GET sur son chemin d'import, en désignant l'élément par sa clé (par exemple ?external_id=…) ou par son identifiant dans votre boutique (?id=…). Les paramètres acceptés par chaque ressource sont indiqués dans sa rubrique.
Remarque — L'API lit un élément à la fois : il n'y a ni liste, ni recherche, ni pagination. Elle ne supprime rien non plus : la suppression se fait dans votre espace de travail, et un import ne fait jamais revenir un élément supprimé.
Dates et montants
Les horodatages, comme created_at, sont envoyés et renvoyés sous forme de nombres entiers de secondes depuis l'epoch Unix, en UTC ; une date dans un autre format est refusée, pas convertie. Dans une réponse, 0 signifie que la date n'est pas renseignée. Les montants sont renvoyés sous forme de chaînes contenant un nombre décimal, par exemple "129.90", afin qu'aucune précision ne soit perdue.
Ordre d'import recommandé
Les éléments font référence les uns aux autres : importez d'abord ceux dont les autres dépendent.
- Catalogue : les caractéristiques, puis les catégories, puis les groupes de produits, puis les produits, puis les avis — voir Catalogue.
- Historique des ventes : les clients, puis les commandes, puis les paiements et les expéditions, puis les remboursements, les retours, les réclamations transporteur, les colis refusés, les mouvements de portefeuille et les demandes d'assistance — voir Commandes & logistique.
- Les bons de réduction, une fois importés les clients auxquels leurs codes sont réservés — voir Bons de réduction.