Journal des modifications de l'API
Journal des modifications de l'API
Aperçu de toutes les modifications et améliorations apportées à l'API REST xoPort.
Versions
v2.122.13 Version actuelle
20 octobre 2026Corrections de bogues concernant le statut des contrats, la liste des produits par catégorie et le compte de crédit, ainsi que le masque des clients OAuth2 et la remise de fidélité dans l'exportation des commandes openTRANS. Comparaison numérique des numéros de version : la version 2.122.13 succède à la version 2.122.12. À partir de la version 4.9.174 de la boutique.
Contrats : statut des contrats
- ⚠️ Modification : le point de terminaison de statut
PUT /Import/JSON/contracts/{id}/status, l’objetstatuset le champcontracts_status_iddans l’importation des contrats vérifient l’ID par rapport aux statuts des contrats de la boutique, comme dans le backend. Jusqu’à la version v2.122.12, le point de terminaison de statut et l’objet effectuaient une vérification par rapport aux statuts de commande, etcontracts_status_idétait écrit sans vérification. Tout statut de contrat de la boutique est valide, y compris un statut désactivé. Récupérez les ID à partir decontracts_statuses[], deGET /Export/JSON/contractsou deerror.valid_status_ids, jamais à partir de/order_statuses. - L'ID est lu de manière stricte : un nombre entier ou une chaîne de caractères composée de chiffres ; les espaces en bordure ne sont pas pris en compte.
true,[65],"1e3"ou54.9ne sont pas des ID : au niveau du point de terminaison de statut HTTP 400INVALID_STATUS, dans l'importation de contrats, l'avertissementCONTRACT_STATUS_UNKNOWN. Jusqu'à présent, cela a donné respectivement 1, 1, 1 000 et 54.
| Cas | jusqu’à la version v2.122.12 | à partir de la v2.122.13 |
|---|---|---|
| Statut de contrat qui n'existe pas également en tant que statut de commande, au point de terminaison de statut | HTTP 400 INVALID_STATUS | enregistré |
… dans l’objet « status » de l’importation de contrats | ignoré sans autre | écrit |
| ⚠️ ID n'existant qu'en tant que statut de commande, enregistré au niveau du point de terminaison de statut | en tant que statut de contrat, new_status_name avec le nom du statut de commande | HTTP 400 INVALID_STATUS |
⚠️ … dans l’objet status de l’importation de contrats | enregistré comme statut de contrat | Statut inchangé, avertissement CONTRACT_STATUS_UNKNOWN |
ID inconnu dans l’objet status ou status sans status_id | a été ignoré sans autre, l’enregistrement a été considéré comme créé ou modifié | Statut inchangé, avertissement CONTRACT_STATUS_UNKNOWN |
⚠️ contracts_status_id sans statut de contrat valide (ID de statut de commande uniquement, 0, "abc", true) | Écrit sans vérification ("abc" = 0, true = 1) | non écrit, les autres champs le sont, avertissement CONTRACT_STATUS_UNKNOWN |
INVALID_STATUSindique les ID valides dans le message et danserror.valid_status_ids. L'avertissementCONTRACT_STATUS_UNKNOWNfigure danswarnings[]et dans l'entrée de l'enregistrement dansrecords[], aveccontracts_idetfield(status.status_id,statusoucontracts_status_id). L'enregistrement continue d'être considéré comme créé ou modifié, seul le statut n'est pas enregistré.new_status_nameLa réponse du point de terminaison de statut contient désormais le nom du statut du contrat.- Un «
contracts_status_id» valide est enregistré comme auparavant, sans inscription dans l’historique des statuts. Pour enregistrer un changement de statut avec historique, utilisez l’objetstatuset le point de terminaison de statut. - ⚠️ Les interfaces qui envoyaient jusqu’à présent un ID de statut de commande comme statut de contrat reçoivent désormais un code HTTP 400 ou l’avertissement (lignes marquées d’un ⚠️). Pour en savoir plus : Contracts.
Liste des produits par catégorie
- ⚠️ Modification :
/categories/{id}/productlistrenvoie exactement cette catégorie,/categories/{a}:{b}/productlistles catégories a à b et/categories/{a}:/productlistles catégories à partir de a. Jusqu’à la version v2.122.12, la liste des produits de toutes les catégories était renvoyée avec un code HTTP 200 ; pour{id}, un avertissement «RANGE_START_NOT_SINGLE_RECORD» s’affichait ; cet avertissement n’apparaît plus ici. - ⚠️ L'ajout de «
?categories_id=» à l'ID ou à la plage dans le chemin d'accès génère une erreur HTTP 400 :FILTER_NOT_APPLICABLE. Seule la même valeur que l'ID du chemin d'accès unique est autorisée. Un?categories_id=vide ou composé uniquement d'espaces est considéré comme non envoyé.
| Requête | jusqu'à la version v2.122.12 | à partir de la v2.122.13 |
|---|---|---|
/categories/5/productlist | HTTP 200, toutes catégories, avertissement RANGE_START_NOT_SINGLE_RECORD | Catégorie 5 |
/categories/5:10/productlist | HTTP 200, toutes les catégories | Catégories 5 à 10 |
/categories/5/productlist?categories_id=5 | Catégorie 5 | inchangé Catégorie 5 |
⚠️ /categories/5/productlist?categories_id=7 | HTTP 200, catégorie 7 | HTTP 400 FILTER_NOT_APPLICABLE |
⚠️ /categories/5:10/productlist?categories_id=5 | HTTP 200, catégorie 5 | HTTP 400 FILTER_NOT_APPLICABLE |
/categories/productlist?categories_id=5 | Catégorie 5 | inchangé |
- ⚠️ Les requêtes comportant un ID ou une plage dans le chemin d’accès et un
?categories_id=différent recevaient, jusqu’à la version v2.122.12, la catégorie du paramètre ; elles reçoivent désormais un code HTTP 400 (lignes marquées d’un ⚠️). Veuillez envoyer la catégorie soit dans le chemin d’accès, soit en tant que paramètre. - En l’absence d’
?language=, le nom de la catégorie s’affiche dans la langue dont l’languages_idest la plus faible (dans les boutiques XONIC, 1 = anglais), et non dans la langue par défaut de la boutique. Jusqu’à présent, l’ordre des lignes dans la table des langues était déterminant, mais celui-ci pouvait varier, par exemple après la suppression et la recréation d’une langue. Envoyez un e-mail à?language=si la langue a son importance. Pour en savoir plus : Catégories.
Compte de crédit : filtre par source
- ⚠️ Modification :
GET /Export/JSON/wallet_logs?source=uniquement avec un espace (?source=%20) signifie « non défini », comme indiqué à l'adresse/orders?source=. Jusqu'à la version v2.122.12, le point de terminaison filtrait alors sur une source vide et renvoyait généralement une liste vide.
| Requête | jusqu’à la v2.122.12 | à partir de la v2.122.13 |
|---|---|---|
/wallet_logs?source=%20 | Filtrage sur une source vide, généralement une liste vide | comme s’il n’y en avait pas source |
/wallet_logs?source=0 | Le filtre est ignoré, comme s’il n’y en avait pas source | uniquement les entrées dont la source est 0 (généralement une liste vide) |
- Inchangé :
?source=avec une autre valeur ; les espaces à la fin de la valeur n’étaient déjà pas pris en compte auparavant.
Backend : clients OAuth2
- Aucune modification de l’API. À partir de la version 4.9.174 de la boutique, la fonction « Modifier le client » affiche à l’administrateur, pour un client illimité, un champ vide avec la mention « Illimité (défini par XONIC) », et le client reste enregistré comme illimité. ⚠️ Jusqu’à la version Shop 4.9.173, la valeur affichée était 5 000, et chaque enregistrement effectué par l’administrateur écrivait 5 000, même si seuls le nom ou la note avaient été modifiés. À lire également : Clients OAuth2, section « Limite de requêtes ».
- Si l’administrateur XONIC crée un client avec un champ vide, celui-ci est désormais toujours illimité ; jusqu’à la version 4.9.173 de Shop, il se voyait attribuer la valeur 5 000 en fonction du schéma de la base de données.
- Lors de la création d’un client, le nom et la note sont enregistrés sans barre oblique inversée supplémentaire (
O'Reillyau lieu deO\'Reilly).
Interface XML : remise de fidélité dans openTRANS
- ⚠️ Modification : l’exportation de commande avec le modèle openTRANS (
/Export/XML/order/{id}/opentrans) affiche la remise de fidélité (ot_loyalty_discount) sous forme de réduction, en tant que ligne comme les autres lignes de total, et l’inclut dansTOTAL_ITEM_NUM. Jusqu’à la version v2.122.12, le modèle demandaitot_loyality_discount(faute de frappe) : la déduction manquait, et les lignes étaient supérieures d’autant àTOTAL_AMOUNT. - Inchangés : le calcul des lignes de total, l’exportation JSON et les autres modèles XML. Les variantes personnalisées du modèle qui ont repris la liste des lignes de total depuis
orders-opentrans.xslconservent la faute de frappe.
v2.122.12
19 octobre 2026Correction d'erreur : les paramètres de requête et les segments de chemin d'accès s'appliquent tels que la boutique les vérifie. Comparaison numérique des numéros de version : la version 2.122.12 succède à la version 2.122.11. À partir de la version 4.9.173 de la boutique.
Espace en fin de chaîne : la valeur vérifiée est prise en compte
- Modification : la validation des valeurs (depuis la v2.122.10) évalue chaque valeur sans espace en bordure : espace (également
+dans l’adresse), tabulation%09, saut de ligne%0A/%0D,%00et%0B. Jusqu’à la version v2.122.11, de nombreux points de terminaison lisaient ensuite la valeur non tronquée, et une valeur qui passait le test s’y comportait en réalité différemment. Désormais, c’est exactement la valeur vérifiée qui s’applique au niveau du point de terminaison, lors des opérations d’exportation, d’importation et de suppression. - Modifications : Une valeur vide ou un espace vide signifie « non défini » pour tout paramètre soumis à une règle fixe (nombre, identifiant, bouton, valeur de sélection, date, heure, langue, nom de fichier, lettres et chiffres), y compris dans les points de terminaison qui, jusqu’à présent, vérifiaient uniquement si le paramètre existait.
| Demande | jusqu’à la v2.122.11 | à partir de la v2.122.12 |
|---|---|---|
?_strict=%20true lors de l’importation | le mode strict est désactivé, l’importation s’effectuait partiellement | en mode strict |
?_strict=true%0A lors de l'exportation, avec un filtre ou un champ inconnu | HTTP 200 avec avertissement | HTTP 400 comme avec ?_strict=true |
/tickets?type=%20job | les tickets et les tâches | uniquement les tâches |
/categories?parent_id=5%00, ainsi que les filtres numériques et de sélection sur les contrats, tickets, projets, tâches, rendez-vous et autres points de terminaison | Filtre supprimé | Filtre appliqué |
/products?bundles=%201, ainsi que « marketplaces » et bonus_free_features | Bloc manquant | Bloc présent |
/products_options_values?orphaned=%20true | toutes les valeurs | uniquement les orphelines |
/porters?status=%20, /products_options?listing_status=%20 | filtrées à 0, c'est-à-dire, pour les porteurs, les inactives | non définies |
/porters?status=%001, /products_options_values?option_id=%005 (%00 avant le chiffre) | lues comme 0 : les ports inactifs ou les valeurs de l'attribut 0 | la valeur envoyée |
/faqs?language=, de même que /faqcats, /cms, /sliders et /categories?language=%20 | une liste vide | toutes les langues, comme sans language |
/medias?entity_type= | une liste vide avec une remarque | les images des produits, comme sans entity_type |
/products_options?with_values= ou %20 | HTTP 400 | non défini |
GET /seohistorys?type=%20p | Entrées de tous les types | uniquement le type p |
DELETE /seohistorys?type=p&base_id=42%00 | a supprimé toutes les entrées de type p | uniquement les entrées de l'article 42 |
DELETE /seohistorys?type=%20p&base_id=42 | a supprimé les entrées de tous les types associées à l'ID 42 | uniquement celles de type « p » associées à l'ID 42 |
⚠️ DELETE /seohistorys?type=%20p sans autre filtre, de même que ?base_id=42%00 ou ?expired=1%00 seuls | HTTP 400 MISSING_FILTER, rien n'est supprimé | supprime toutes les entrées de type « p » portant l'ID 42 ou toutes celles qui ont expiré |
⚠️ DELETE /medias?entity_id=7%00 | HTTP 400 NO_TARGETS ou uniquement les ID figurant dans le corps du message | ainsi que toutes les images de l'article 7 |
⚠️ DELETE /ticket_department/{id}?reassign_to=%005 | HTTP 409 DEPARTMENT_IN_USE | Tickets déplacés vers le service 5, service supprimé |
- ⚠️ Une suppression ne supprime jamais plus que ce qu’indiquent les valeurs vérifiées, mais elle supprime toutefois davantage qu’avant la version v2.122.11 : les requêtes qui étaient jusqu’à présent rejetées faute de condition valide sont désormais supprimées (lignes marquées d’un ⚠️).
- Inchangé : valeurs sans espace à la fin, texte libre (mots-clés, noms, codes), filtres avec vérification de valeur propre (filtres produit, client et bon de réduction ; pour les commandes, date et pays de livraison ; là, la valeur vérifiée s’appliquait déjà) ainsi que la navigation et le tri. Tous les cas : API d’exportation, section « Espace libre en bordure ».
Segment de chemin dans l’export JSON
- Modifié : le segment suivant le point de terminaison est un nombre entier comportant au maximum 18 chiffres (
/product/42), une plage avec des limites entières (/orders/100:200,/orders/100:),new:{datum}vers les clients et les commandes ou la sous-routeproductlistvers/categories. Tout autre cas génère une erreur HTTP 400INVALID_RANGE, et le message indique le segment concerné. Jusqu’à la version v2.122.11, un segment invalide renvoyait la liste paginée avec un code HTTP 200. - Les espaces vides en bordure du segment ne comptent pas :
/product/42%20correspond à l’article 42. Un segment composé uniquement d’espaces vides renvoie un code HTTP 400.
| Requête | jusqu'à la version v2.122.11 | à partir de la version 2.122.12 |
|---|---|---|
/product/42%20, /order/42%0A | HTTP 200, la liste | Enregistrement 42 |
/product/42x, /order/42%2B, /product//42, /products/productlist | HTTP 200, la liste | HTTP 400 INVALID_RANGE |
⚠️ /product/42.0, /order/+5, /product/1e3, /products/1.5:3 | Enregistrement 42, 5 ou 1 000, plage de 1 à 3 | HTTP 400 INVALID_RANGE |
⚠️ /orders/new%3A2026-10-01 (deux-points codé) | HTTP 200, la liste complète au lieu du delta | HTTP 400 INVALID_RANGE |
⚠️ /contracts/10/20 | Contrats à partir de 10 sans limite maximale | HTTP 400 ; la plage est /contracts/10:20 |
/categories/5/Productlist, /product/42/x | catégorie 5 ou article 42 | HTTP 400 INVALID_RANGE |
/orders/ avec 19 chiffres ou plus | une limite au-delà de tout identifiant, à partir de 309 chiffres, la liste complète | HTTP 400 INVALID_RANGE |
- ⚠️ Même les interfaces qui recevaient jusqu’à présent l’enregistrement souhaité reçoivent désormais un HTTP 400 (lignes marquées d’un ⚠️) : envoyez l’ID sous forme de nombre entier sans décimales ni signe, ce qui est généralement le cas pour les valeurs issues de tableaux. Envoyez le double-point après «
new» sans le coder. /categories/{id}/productlistreste autorisé, mais l'ID n'est pas pris en compte : la réponse contient toutes les catégories (à partir de la v2.122.13, filtre par catégorie, voir cette version). Pour récupérer une catégorie, utilisez/categories/productlist?categories_id={id}.- Inchangé : exportation au format XML, CSV et TXT (dans ce cas, un segment sans nombre correspond au nom d’un modèle), importation et suppression. Envoyez également les ID sous forme de nombres entiers lors de la suppression.
v2.122.11
18 octobre 2026Troisième partie des extensions pour les intégrations avec la gestion des stocks et l’automatisation, notamment lors de la création. Comparaison numérique des numéros de version : la version 2.122.11 succède à la version 2.122.10. À partir de la version 4.9.171 de la boutique.
Commandes
- Modification : si une interface envoie les prix des lignes avec l’
tax_flage 1 (brut), la boutique enregistre désormais la ligne au prix net, comme pour une commande provenant de la caisse, y compris les majorations propres aux caractéristiques. Auparavant, le prix brut figurait dans la ligne de commande, et l’éditeur de commande, le PDF de la facture, l’e-mail de commande ainsi que l’ajout ultérieur de lignes de commande appliquaient la taxe une deuxième fois.orders:readfournit donc ces lignes de commande au prix net (products_price,final_price,attributes[].options_values_price; 10,00 à 19 % devient8.40336134). Les interfaces qui récupèrent ces champs et les comparent aux données envoyées procèdent à la conversion. Les montants totaux de la commande restent inchangés. - Dans deux cas, c’est désormais la valeur de la caisse qui s’applique : le supplément lié aux caractéristiques présélectionnées (
apply_default_attributes) sur un tel poste est pris en compte dans le calcul de la taxe, et un barème de frais de port en fonction de la valeur des marchandises (compute_shipping) se base sur la valeur nette. Les frais d’expédition et le montant total peuvent ainsi varier ; une commande «expected_total» adaptée à l’ancienne valeur indique alors «TOTAL_DRIFT». Les commandes existantes ne sont pas converties ; si l’on ajoute quelque chose à une ancienne commande dont les lignes sont enregistrées en brut, la double taxation reste en vigueur. - Nouveau : champ de position «
service» lors de la création (POSTetPUTavecproducts_mode: "append") :1= prestation de service,0= marchandise, ainsi quetrue/falseou"1"/"0". La valeur envoyée prévaut sur les données du produit, par exemple dans le cas d’un poste de prestation de service libre sansproducts_idpour un client professionnel situé dans un autre pays de l’UE. Sans ce champ, la règle du produit s'applique comme auparavant : un poste libre correspond à une marchandise. Une autre valeur génère l'avertissement «service_invalid» dansrecords[].warnings. Jusqu'à présent, le champ était ignoré (UNKNOWN_FIELD). - Modification : «
products_mode: "update"» rejette «service». L'enregistrement échoue avec le message «FIELD_NOT_UPDATABLE», rien n'est écrit, pas même dans les autres champs. Jusqu'à présent, un avertissement s'affichait et l'enregistrement était considéré comme «updated». - Modification : la ligne d’expédition d’une commande hors taxes (
tax_flag0) comportetax0 et le taux d’imposition danstax2, comme une commande hors taxes issue de la caisse ; les commandes exonérées d’impôt (tax_flag2) comportent également 0 et 0 en modeverbatim. Si l’on lit le taux d’expédition uniquement à partir detotals[].tax, on utilisetax2pour les commandes nettes. Les totaux restent identiques, les commandes enregistrées ne sont pas modifiées. La facture électronique de ces commandes indique désormais le montant correct pour l’expédition. - Lors de l’ajout de lignes via
PUT, les frais d’expédition d’une commande nette provenant de la caisse sont désormais pris en compte ; auparavant, ils n’apparaissaient pas dans le total général.
Clients : désabonnement à la newsletter
- Nouveau :
customers_nl_lockest accessible en écriture viaPOST/PUT /customers:0/1,true/falseou"0"/"1". La valeur exportée peut être renvoyée, notamment via?_strict=true. Si la valeur est manquante, si elle est «null» ou vide, le blocage reste inchangé. Une valeur invalide génère l'avertissement «INVALID_FIELD_VALUE», le reste de l'enregistrement est enregistré. Jusqu'à présent, le champ était «UNKNOWN_FIELD» (avec «?_strict=true» et un code HTTP 400). - Modification :
1désabonne tous les abonnements du compte, dans la boutique et auprès du fournisseur de newsletter. Le désabonnement est alors considéré comme une opposition à la publicité et reste valable même après0; les importations ultérieures rejetteront l’adresse. Une exportation renvoyée aveccustomers_nl_lock = 1entraîne également la désinscription ; chez le prestataire, cela ne peut pas être annulé, un abonnement ne peut être réactivé qu’après une nouvelle confirmation. Si le prestataire échoue, la réponse indiqueNEWSLETTER_UNSUBSCRIBE_FAILED; le blocage est enregistré, l’abonnement est maintenu.0ne fait que lever le blocage. - ⚠️ Les e-mails publicitaires issus du marketing et des automatisations (xoMarketing) ne sont pas encore bloqués dans Shop 4.9 ; cette fonctionnalité sera disponible à partir de Shop 4.10.
- Les désabonnements auprès du fournisseur s’effectuent directement dans la requête elle-même, à raison d’un par adresse. Il est donc conseillé de diviser en lots plus petits les grands lots comportant de nombreux comptes bloqués.
- Dans le CSV-Porter (colonne « customers newsletter lock ») et dans l’importation de clients au format XML (colonne «
customers_nl_lock», uniquement avec votre propre XSL, réponsenewsletter.locked_removed), la valeur «1» est également renseignée. Contrairement à l’API, une cellule vide ou toute autre valeur lève le blocage dans ces cas-là. Le message de refusNEWSLETTER_LOCKEDenvoyé àPOST /newsletter_subscribers(pour les clients utilisantcustomers:read, sinonNOT_SUBSCRIBABLE) indique désormais la marche à suivre pour lever le verrouillage :PUT /customersaveccustomers_nl_lock = 0.
Projets
- Nouveau :
relationships[]permet également de lier un projet à des contrats (target_typecontracts_id). Jusqu’à présent, un tel enregistrement échouait (« Invalid relationships »). - Modifié : un lien vers une commande, un ticket ou un contrat inexistant n’est plus créé, mais le reste de l’enregistrement est conservé ;
warnings[]signalePROJECT_RELATIONSHIP. Si vous renvoyez une exportation viaPUT, vous perdez les liens vers les cibles supprimées, carPUTremplace tous les liens. - Modification : si
relationshipsn’est pas une liste, l’enregistrement échoue. Jusqu’à présent,POSTcréait le projet sans liens, etPUTles supprimait tous en silence. L’exportation ne fournit désormais plus que des liens des trois types suivants :orders_id,ticket_idetcontracts_id.
Caractéristiques
- Si
POST/PUT /products_optionsmodifie une valeur qui est également liée à une autre caractéristique, un clone avec un nouvel identifiant est créé, comme auparavant. Le clone reprend désormais de l’original lesimageetsort_idnon envoyées ; auparavant, il recevait une image vide et le tri 0. Les valeurs envoyées prévalent. Les clones déjà créés restent tels quels : ajoutez l’image et le tri viaPUT.
Produits : lots
- Nouveau : champ «
bundle» sur le produit, contenant les paramètres et les composants d’un lot. L’exportation ne le fournit qu’avec «?bundles=1», y compris lors d’une consultation individuelle et dans les sections ; sans lot, la valeur «null» y figure. «?bundles=» n’accepte que «0» ou «1», sinon une erreur HTTP 400 est renvoyée. - Modification : auparavant, un
bundleenvoyé en paramètre était ignoré et traité commeUNKNOWN_FIELD. Désormais, c’est le bundle qui le modifie :nullle supprime,items[]remplace tous les éléments ; sans la clé, rien ne change. Unbundlenon valide entraîne l'échec de l'ensemble de l'enregistrement (INVALID_BUNDLE) ; rien n'est écrit, pas même le prix.bundle_auto_priceetbundle_auto_price_percentn'existent pas dans la version 4.9 de la boutique (avertissementBUNDLE_SETTING_UNAVAILABLE). - Pour les boutiques provenant d'une version antérieure à la 4.9.155 : après la mise à jour, ouvrez une fois le backend avant que la connexion n'enregistre les bundles.
Produits : places de marché
- Nouveau :
?marketplaces=1fournit, pour chaque article,marketplaces[], une entrée par canal de la boutique avec un bouton et un statut :code,status,upload_status,sync_state,last_updated,external_id,messages[]et d’autres. Dans la version 4.9 de la boutique,livecorrespond toujours ànull. Une valeur différente de0/1génère une erreur HTTP 400 au lieu de l’avertissementUNKNOWN_FILTER. - Nouveau : l'envoi de
marketplaces[]àPOST/PUT /productsactive le commutateur pour chaque canal (canal viacodeoumarketplace_id,status,0/1) ; les canaux non envoyés restent inchangés. L'écriture ne s'effectue que pour les canaux disposant d'une licence dans la boutique. Jusqu'à présent, la clé étaitUNKNOWN_FIELD. - Le commutateur prend effet lors de la prochaine synchronisation du canal : pour Amazon, eBay, Kaufland et Idealo,
1crée une offre, tandis que0la supprime. Les canaux Mirakl et Shöpping.at ne suppriment pas les offres avec0; Mirakl ne crée une offre qu’avec des données Mirakl mises à jour ; Check24, Etsy et les canaux sans connexion ne transfèrent rien depuis la boutique (détails sur la page « Products »). Une exportation renvoyée avecmarketplaces[]inclut également les commutateurs. UnPUTcontenant uniquement l’identifiant de l’article (products_idouproducts_model) etmarketplacesne modifie pas la date de modification de l’article ; la ligne de canal modifiée est marquée pour la synchronisation (last_updated1970-01-01 00:00:00). - Nouveau : filtre de la place de marché sur
/products:?marketplace=avec?marketplace_status=,?marketplace_upload_status=ou?marketplace_sync_state=, par exemple pour récupérer tous les articles Idealo non à jour en une seule fois. Jusqu’à présent, les noms étaient ignorés (UNKNOWN_FILTER) et la liste était renvoyée sans filtrage. - Modification (Idealo) : un retrait (
status0 via l’API, le masque d’article, CSV ou XML) est désormais également pris en compte lorsque le stock est nul. Seule une offre que la boutique a elle-même désactivée en raison d’un stock égal à 0 est réintégrée ; elle reste ensuite disponible surpendingjusqu’à la prochaine synchronisation. Si un filtre de synchronisation a désactivé l’offre (par exemple en raison de l’absence d’image ou de GTIN), celle-ci ne réapparaît pas automatiquement une fois le problème résolu : renvoyerstatus1. - Fiche produit : les validations et les données de canal ne sont désormais enregistrées qu’après un enregistrement réussi. Les données de canal d’un canal qui a été activé entre l’ouverture et l’enregistrement, par exemple via l’API, sont conservées. Le bouton lui-même est toujours réinitialisé à son état initial lors de l’enregistrement d’un masque précédemment ouvert : recharger les masques ouverts après une validation via l’API.
Produits : sélection des champs
- Nouveau :
?fields=dans l’exportation des produits indique les clés par produit, par exemple?fields=products_model,products_price,products_quantity;products_idest toujours inclus. Seules les données nécessaires sont chargées : lors d’un test, une page contenant 250 articles est passée de 4,3 Mo à 52 Ko. Les clés non mentionnées sont totalement absentes, au lieu d’être vides. Une sélection peut être renvoyée viaPUTet ne modifie que les éléments qu’elle contient. - Modifié : Si vous envoyez déjà
?fields=, vous ne recevez désormais que les clés mentionnées au lieu de l’ensemble du jeu de données, avec l’avertissementUNKNOWN_FILTER. Une liste invalide génère une erreur HTTP 400INVALID_FILTER_VALUE, un nom inconnu entraîne l’avertissementUNKNOWN_FIELD(avec?_strict=true, erreur HTTP 400).bundle,bonus_free_featuresetmarketplacesdemandent le nom via?fields=; le commutateur seul ne fonctionne alors pas (avertissementSWITCH_IGNORED).
Limite de requêtes
- Nouveau : chaque réponse adressée à un client soumis à une limite de requêtes comporte les en-têtes
X-RateLimit-Limit,X-RateLimit-RemainingetX-RateLimit-Reset.GET /meindique à cet effetrate_limit_window,rate_limit_remainingetrate_limit_reset. - Modification : pour le code d'état HTTP 429,
Retry-Afterindique le nombre de secondes jusqu'à la prochaine acceptation (de 1 à 3 600) au lieu d'une valeur fixe de 3 600, et la réponse contienterror.retry_after. Le message est désormais « Rate limit of N requests per 3 600 s (sliding window) exceeded. » ; Les connexions analysenterror.code, et non le texte. Au niveau du point de terminaison du jeton,Retry-Afterest également calculé (de 1 à 300).
Adresse de la boutique → ID
- Nouveau : filtres précis pour les adresses de la boutique :
?seo_string=vers/categorieset/seohistorys,?seo_name=vers/products. Pour une adresse provenant de la Search Console, d’un ancien plan du site ou d’un e-mail client, on obtient ainsi la catégorie, l’article ou la destination d’une redirection. Jusqu’à présent, les nomsUNKNOWN_FILTERétaient signalés, et la liste était fournie sans filtrage. Plusieurs résultats sont renvoyés. Si deux catégories partagent une même adresse, la boutique effectue le choix sans ordre défini : le premier résultat n’est pas nécessairement la page affichée. - Modification :
DELETE /seohistory(s)?seo_string=renvoie un code HTTP 400, rien n’est supprimé. Jusqu’à présent, le nom était ignoré et seules les entrées?type=/?base_id=étaient supprimées. Les entrées se suppriment via leursh_id. - Modification : une valeur composée uniquement de virgules sur
products_model,products_eanetseo_name(/products), ainsi que suremail,lastname,companyetcustomers_id_extern(/customers) renvoie un code HTTP 400 au lieu de la liste non filtrée. Un élément vide entre les valeurs continue d’être ignoré.
Valeurs non valides
- Modifié :
GET /coupons?type=ne contenant que des virgules, par exemple une liste vide, renvoie un code HTTP 400 au lieu de la liste complète des coupons avec les codes de crédit. - Modification : un filtre de date composé uniquement de signes de ponctuation (
?date_to=,,?last_modified=.,?valid_on=,) renvoie un code HTTP 400INVALID_FILTER_VALUE; auparavant, il était interprété comme « maintenant ». Cela concernedate_frometdate_tovers/tickets,/contracts,/projects,/appointmentset/wallet_logs,due_frometdue_tovers/project_tasks,sincevers/medias,last_modifiedvers/productsetvalid_onvers/coupons. Un espace vide est désormais systématiquement interprété comme « non défini ». Un «+» dans l'adresse correspond à un espace ; envoyez un « + » à l'adresse%2B. - Modifié :
POST /mediaetPUT /media/{id}: un champ contenant exactement une valeur sous forme de liste (entity_id[]=5, un tableau dans le corps JSON) renvoie une erreur HTTP 400INVALID_FIELD_VALUEavecfield; rien n’est lu ni écrit. Auparavant, on obtenait une erreur HTTP 500 ou une autre valeur, comme l’image de l’article 1. Les fichiers multiples sont traités comme plusieurs appels. - Les réponses d'erreur contenant du code UTF-8 non valide dans un nom ou une valeur répété(e) s'accompagnent désormais d'un corps de réponse, les caractères illisibles étant remplacés par
U+FFFD: noms de paramètres inconnus (avertissementUNKNOWN_FILTER, auparavant une réponse vide), les rejets liés à la validation des valeurs renvoient un 404 vers/ticket_attachment/{id}et les erreurs dePOST /mediasont renvoyées sous la formemultipart/form-data. - D'autres corrections de la validation des valeurs concernent des points de terminaison internes.
Point de terminaison des jetons
- Modification : une portée demandée qui ne peut pas être lue (UTF-8 non valide ou une liste telle que
scope[]=…) renvoie une erreur HTTP 400invalid_scope; aucun jeton n’est émis.client_idouclient_secretsous forme de liste renvoient une erreur HTTP 400invalid_request.
E-mails, n8n et historique des commandes
- Les textes libres, les données client, les prix et les saisies dans les formulaires apparaissent mot pour mot dans le corps de l’e-mail, l’objet et l’historique des commandes ; un «
$» suivi d’un chiffre ne se perd plus (auparavant, « Nachnahme $100 » devenait « Nachnahme 0 »). Cela s’applique également aux e-mails qui déclenchent une intégration. - Le nom, la raison sociale et l’adresse issus de la commande et du compte client ne sont désormais insérés par la boutique dans les e-mails que sous forme de texte. Les nouvelles entrées de l’historique résultant de changements de statut, dont le texte utilise des espaces réservés, comportent donc ces valeurs masquées (
GET /orders→status_history[].comments, par exempleMüller & Söhne), tout commecommentdans l’événement n8norder.status_changed;comment_textreste en texte clair. Les entrées existantes sont conservées.
Perspectives
- La version 4.10 de Shop apportera, entre autres, de nouvelles fonctionnalités pour les offres groupées, le statut en temps réel par place de marché (
live),?fields=sur d’autres listes et avec des sous-clés, de nouvelles options de recherche sur/seohistorysainsi que des renforcements de sécurité internes supplémentaires.
v2.122.10
15 octobre 2026Deuxième partie des extensions pour les connexions au système de gestion des stocks et à l’automatisation, notamment en lecture. Comparaison numérique des numéros de version : la version 2.122.10 succède à la version 2.122.9. À partir de la version 4.9.169 de la boutique.
Clients : références de commande et paniers
- Nouveau : chaque client dispose des indicateurs «
order_stats» avec les valeurs «orders_count», «orders_count_valid», «first_order_date», «last_order_date», «first_valid_order_date» et «last_valid_order_date». Les valeurs «valid» ne tiennent pas compte des commandes annulées ni des devis. Les interfaces strictes en termes de types de données doivent prendre en compte ce nouveau champ. - Nouveau : filtre
?ordered_since=sur/customerspour les clients ayant au moins une commande à partir de cette date. - Nouveau :
GET /customers_baskets,/customers_basket/{customers_id}et la section/customers_baskets/{von}:{bis}fournissent le panier de chaque client avec les lignes, les caractéristiques,basket_last_modifiedetlast_activity. Filtres :customer_id,sinceetbasket_type. Un panier vide n’apparaît pas. - Le périmètre
customers:readcouvre ainsi les paniers et les indicateurs de commande. Veuillez vérifier les autorisations des clients et votre propre politique de confidentialité.
Formats de chemin d'accès et moments
- Les formats de chemin d’accès de
/orderset/customers, par exemple/order/{id},/orders/{von}:{bis}et/orders/new:{datum}, parcourent désormais la base de données par ordre croissant d’ID. Les grandes plages ne provoquent ainsi plus d’erreur de mémoire. Sans?limit=, la réponse reste non triée jusqu’à la limite maximale ; au-delà, elle est fournie en taille standard avechas_more. - Modifié :
new:{datum}est vérifié (YYYY-MM-DD,YYYY-MM-DD HH:MMouYYYY-MM-DD HH:MM:SS), sinon HTTP 400INVALID_RANGE. Si l’heure est indiquée, la précision est à la seconde près. Ce format n’est désormais valable que pour/customer(s)et/order(s); les autres points de terminaison renvoient un code HTTP 400 et indiquent, le cas échéant, leur filtre de date. - Modification : les dates et heures dans les filtres doivent désormais être exprimées sous des formes fixes :
YYYY-MM-DD,YYYY-MM-DD HH:MMouYYYY-MM-DD HH:MM:SS, avec le fuseau horaire en option (Zou±HH:MM; envoyer le signe « + » sous la forme%2B). Les indications telles queyesterdayou01.10.2026génèrent une erreur HTTP 400INVALID_FILTER_VALUE. Cela concerne/customers,/customers_baskets,/newsletter_subscribers,/orderset/coupons. - Nouveau :
?last_modified=vers/orders, en tant qu’autre orthographe desince(remarqueFILTER_ALIAS). - Modification :
/customers/{von}:et/products/{von}:sont désormais des plages ouvertes à partir de l'ID indiqué. Auparavant, les deux ne renvoyaient qu'un seul enregistrement.
Paramètres de requête non valides
- Modification : les valeurs non valides et les valeurs de liste (
?x[]=,?x[k]=) génèrent une réponse HTTP 400INVALID_FILTER_VALUEavecdetails[]sur tous les points de terminaison JSON. La validation s'effectue avant toute lecture, écriture ou suppression. Jusqu’à présent, un tel filtre était parfois omis, et la réponse contenait le contenu non filtré. Les valeurs valides restent inchangées, une valeur vide est considérée comme non définie. - À l'adresse
/orders, une liste séparée par des virgules, un texte ou un nombre décimal renvoie une erreur HTTP 400 aux adressesstatus,customer_id,marketplace_id,products_idetcategories_id. Plusieurs pays de livraison sont indiqués sous forme de liste séparée par des virgules à l'adressedelivery_country. /categories/productlistacceptecategories_idetinclude_inactive_productssans avertissement.parent_idetrecursivene fonctionnent pas à cet endroit et renvoientUNKNOWN_FILTER.
Abonnés à la newsletter
- Modification : l'envoi de
?last_modified=à/newsletter_subscribersfournit également les abonnés ayant confirmé leur inscription par double opt-in ou dont le transfert vers le prestataire de la newsletter est encore en attente. Le delta s'en trouve ainsi accru. Les adresses supprimées et désabonnées ne figurent dans aucun delta ; il est donc recommandé de procéder régulièrement à une synchronisation complète. - Nouveau :
customer_idetlanguage_idsous forme de liste séparée par des virgules.?email=continue de rechercher une partie de l’adresse, tandis que%et_sont considérés comme des caractères. La liste parcourt la base de données.
Produits
- Nouveau : données bonus et gratuites de l’article sous forme de bloc
bonus_free_features(status_bonus,bonus_points,max_bonus,status_free,bonus_value,max_free,auto_free). L’exportation ne les fournit qu’avec?bonus_free_features=1. Lors de l’importation, une clé manquante laisse les données inchangées,nullles supprime, un objet ne modifie que les champs envoyés. Les valeurs non valides entraînent le rejet de l'enregistrement (INVALID_BONUS_FREE_FEATURES), le blocage d'importationbonusest respecté. - Modifié : un article inexistant renvoie, lors d’une requête individuelle (
/product/{id}), un code HTTP 404NOT_FOUNDau lieu d’un code HTTP 200 avec une entrée videdata. - Modification : les articles sans image principale ne renvoient plus d’entrée d’image vide (
images_id0). Les exportations plus anciennes contenant cette entrée peuvent être renvoyées sans erreur ; l’image principale enregistrée est conservée. - Modification :
products_statusne peut prendre que la valeur 0 ou 1. La boutique définit elle-même le statut 2 lorsque l’article ne dispose pas d’un chemin de catégorie actif de bout en bout (avertissementNO_ACTIVE_CATEGORY_PATH). Une valeur 2 envoyée ou une valeur non valide n’est pas enregistrée (READONLY_VALUEouINVALID_FIELD_VALUE). Nouveauté dans la réponse :records[].products_status. - Modification : «
products_xoport» accepte au maximum 64 caractères. Une valeur plus longue entraîne le rejet de l'enregistrement, au lieu d'être raccourcie en silence. - Nouveau : blocage d’importation
costpour le prix d’achat, configurable viaimport_blocks. Vérifier au préalableapi_version: les boutiques plus anciennes n’enregistrent pas ce type, et jusqu’à la version 2.122.8, une liste ne supprime que les blocages existants decost.
Bons d'achat
- Nouveau : la commande
?last_modified=vers/couponsfonctionne sans avertissement, même avec?_strict=true. - Modification : les valeurs de liste dans les filtres de bons et les dates hors des formats prédéfinis génèrent une erreur HTTP 400 au lieu d’afficher la liste complète des bons. Les copies issues de la fonction « Copier un bon » apparaissent dans le delta avec leur date de création.
Statut de la commande
- Nouveau :
GET /order_statuses,/order_status/{id}et les sections fournissent tous les statuts de commande avec des noms par langue, des couleurs, un tri et les indicateursis_default,is_cancelled,is_offer,counts_as_revenue,is_paidetis_shipped. Portée :orders:read; un statut inexistant renvoie une erreur HTTP 404.
n8n et les entrées plus anciennes
- Modifié : l’événement n8n
order.status_changedcontient désormais égalementcomment_texten texte clair.commentcontient le texte de l’entrée d’historique avec les espaces réservés remplacés ; les messages contenant$sont conservés tels quels. - Supprimé : les anciennes entrées
api/n8n/etapi/order-status.phprenvoient une réponse HTTP 404. Les changements de statut s'effectuent viaPUT /Import/JSON/orders.
Portes CSV et XML
- Rubrique CSV « Module Bonus/Gratuit » : une cellule vide définit la valeur sur 0, une colonne manquante la laisse inchangée. Les catégories ayant le statut
delsuppriment toute la branche. - Importation de produits au format XML : un nœud vide
<bonus_free_features>laisse le statut « Bonus » et « Gratuit » inchangé, tandis qu’un 0 explicite le désactive.
v2.122.9
13 octobre 2026Première partie des extensions pour les connexions à la gestion des stocks et à l’automatisation. À partir de la version 4.9.168 de la boutique.
Commandes
- Nouveau : filtre
?delivery_country=à/ordersavec les codes pays ISO, à deux ou trois chiffres et séparés par des virgules. Un code inconnu renvoie une erreur HTTP 400INVALID_FILTER_VALUE. - Modification : les filtres appliqués à une forme de chemin de type
/order(s)s’appliquent désormais en plus de la forme de chemin. Auparavant, ils la remplaçaient :/order/{id}?status=3renvoyait toutes les commandes ayant le statut 3.
Produits
- Modification : l’exportation des produits ne contient que les articles de la requête, aucun élément sans
products_id. Les éléments de typexsellssont exportés dans leur intégralité et placés aprèssort_order; les éléments de typeunit_single,unit_multietunit_basesont renseignés, tandis que ceux sans unité sont laissés vides au lieu denull. L’exportation personnalisée peut être renvoyée via?_strict=true; les champs en lecture seule sont signalés parREADONLY_FIELD. - Modification : une liste
import_blockssans entrée exploitable ne modifie plus les blocages ; auparavant, tous étaient supprimés. Tous les types de blocage de la boutique peuvent être définis. Nouveauté :import_blocks_mode(replace,mergeouappend,remove) etrecords[].import_blocks. Les anciennes boutiques ignorent ce mode ; il faut donc l'envoyer uniquement avec?_strict=true. - Modifié : un
categories_modeinvalide, une catégorie inconnue, uncategoriesou unimagessans liste, ainsi qu’unimages[]sans entrée valide entraînent le rejet de l’enregistrement avant son écriture (INVALID_CATEGORIES_MODE,INVALID_CATEGORIES,INVALID_IMAGES). Auparavant, il était parfois enregistré. Chaque rejet est répertorié avec son code dansrecords[]. - Modification :
options_replace,options_strict_names,apply_value_defaults,videos_replaceetcustomers_prices_replacene s’activent qu’avectrue,1,"1"ou"true";"false"et"no"ne s’activent plus. - Nouveau : les téléchargements d’images (
POST /media,PUT /media/{id}avec fichier) signalentreplaced_existingetthumbnails_removed. Un cache en amont tel que Cloudflare n’est pas vidé dans ce cas ; surreplaced_existing: true, actualisez vous-même l’adresse de l’image. - L'importation de produits avec MPN ne se termine plus par une erreur HTTP 500 sur les boutiques non connectées à eBay. Après une importation depuis
shop_idssous forme de liste, l'interface d'administration affiche correctement les boutiques associées.
Bons d'achat
- Modification :
restrictions.categoriescontient désormais également des catégories enregistrées avec des sous-catégories ; la nouvelle adresse estrestrictions.categories_with_subcategories. Les intégrations voient ainsi davantage d’identifiants de catégories. - Modification :
coupon_codereste du texte, même pour les codes purement numériques tels que « 4711 ». Vérifiez les comparaisons de type exact.
Configuration
- Modifié : les identifiants d’accès, les clés de licence, de session et d’interface, ainsi que les paramètres internes, ne sont ni lisibles ni modifiables via
/configuration, même s’ils sont partagés (CONFIG_KEY_BLOCKED). Retirez ces clés de la liste de partage ; si des identifiants d’accès étaient partagés, renouvelez-les auprès du fournisseur. - Modifié :
PUT /configurationn'écrit que du texte en clair et des nombres entiers dans les limites du masque du backend. Les clés qui déclenchent une action consécutive dans le backend sont en lecture seule et sont modifiées dans le backend.
Abonnés à la newsletter
- Modification :
POST /newsletter_subscribersrejette les adresses faisant l’objet d’un blocage de la newsletter ou d’une opposition à la publicité (NEWSLETTER_LOCKED,OPTED_OUTouNOT_SUBSCRIBABLE). Les adresses désabonnées ne peuvent être réabonnées qu’avecsend_doi. - Modification : dans la boutique « double opt-in », une requête POST sans
subscribe_confirmenvoie elle-même l'e-mail de confirmation, à raison d'un maximum d'un par adresse toutes les 24 heures. - Nouveau :
send_doi,records[].confirmedetrecords[].doi_mail.subscribe_confirmn’accepte qu’une date/heure ou une réponse oui/non. La requête PUT ne confirme plus rien (FIELD_IGNORED_ON_UPDATE). - Modification :
DELETE /newsletter_subscriber(s)vérifie le résultat auprès du fournisseur de la newsletter. Si la désinscription échoue à ce niveau, le chemin unique renvoie un code HTTP 502NEWSLETTER_UNSUBSCRIBE_FAILED. - Importation de clients au format XML :
<newsletter>0désabonne l'adresse et enregistre une opposition à la publicité.
n8n, webhooks et envoi
- Modification :
order.status_changedn’est utilisé qu’en cas de changement de statut réel ; désormais avecold_status. Les événements ne sont envoyés qu’une fois que la modification signalée a été enregistrée. La signature est générée comme auparavant à partir du contenu envoyé ; l’exemple de vérification de la documentation a été corrigé. - La réaction marketing « Envoyer un webhook » se répète après un échec, au lieu de bloquer la cible.
compute_shippingPour une valeur de marchandise égale à 0, elle renvoie la ligne d’expédition au lieu de l’avertissement «SHIPPING_AUTO_FAILED».
Interface XML
- Modification : «
<products_to_marketplaces>» sans entrées n’a plus d’effet ; auparavant, toutes les autorisations étaient mises à 0. Les entrées ne s’appliquent qu’aux places de marché connues et sous licence ayant le statut 0 ou 1. Les flux qui souhaitaient tout désactiver à l’aide d’un nœud vide envoient désormais des entrées avec le statut 0. Nouveau bloc de réponse «marketplaces».
v2.122.8
11 octobre 2026Corrections de bogues
- Enregistrement des commandes (
orders:write) : les lignes de commande présentant un montant de taxe négatif, comme les remboursements, disposent désormais de leur propre ligne de taxe. Lors de l’ajout de lignes de commande via PUT, la taxe des lignes négatives est prise en compte ; auparavant, le total était trop élevé. - Lors de la création de nouveaux postes de commande, le système vérifie, comme lors du paiement, s’il s’agit de marchandises ou d’un service. Les documents relatifs aux livraisons et prestations intracommunautaires restent ainsi cohérents.
/cms,/faqcatset/faqs: les filtres?status=et?module=(uniquement/cms) renvoyaient une erreur HTTP 500 sans format de chemin. Désormais, le filtrage s’effectue sans avertissementUNKNOWN_FILTER.?module=est le code exact du module.DELETE /customerAnonymise au préalable l'historique des produits consultés par le client.- Importation de catégories XML : les champs vides ne remplacent plus rien. La réponse mentionne en outre
categories{inserted, updated, unchanged, deleted, paths_changed, cyclic_parents}. - Importateur CSV : l’importation des caractéristiques définit le statut pour l’ensemble de la chaîne de caractéristiques. Les flux convertissent les montants en devises étrangères. À partir de la version 4.9.167 de la boutique.
v2.122.7
6 octobre 2026Les blocages des groupes de clients lors de l’importation
restricted_customer_groupssur les produits et les catégories ne prend en compte que les groupes de clients existants, sous forme de nombre entier. Si la liste ne contient aucun groupe existant ou s’il ne s’agit pas d’une liste, les blocages enregistrés restent inchangés (avertissementCUSTOMER_GROUP_RESTRICTION_KEPT). Un article nouvellement créé lors de cette opération ne présente aucun blocage.- La présence d’entrées inconnues à côté d’entrées connues déclenche l’avertissement «
CUSTOMER_GROUP». La commande «[]» continue de lever toutes les restrictions ; les listes valides fonctionnent comme auparavant. La même règle s’applique dans le CSV-Porter. À partir de la version 4.9.155 de la boutique.
v2.122.6
6 octobre 2026Exporter les avis sur les produits
- Nouveau :
GET /reviews,GET /review/{reviews_id}et la sectionGET /reviews/{von}:{bis}avec la portéeproducts:read. Jusqu’à présent, l’API ne fournissait pour chaque produit que la moyenne et le nombre d’avis (products_rating,products_rating_count). - Par avis :
reviews_id,products_id,products_model,reviews_rating,status,promo_status,author,verified_purchase,helpful_count,review_external_id,date_added,last_modifiedetdescriptions[]; par langue avecreviews_title,reviews_textetreviews_reply(réponse de la boutique). - Filtres :
products_id(également sous forme de liste séparée par des virgules),status(1= validé, valeur par défaut ;0= en attente de validation ;all) etsince(créé ou dernière modification à partir de). La navigation s'effectue comme pour les produits aveclimitetpage. - Pas de données client :
authorest le nom qui s'affiche également sur la page du produit. Le point de terminaison ne fournit pas l'identifiant client, l'adresse e-mail ni le numéro de commande, mais uniquementverified_purchase. À partir de la version 4.9.153 de la boutique.
v2.122.5
1er octobre 2026Interface XML : exportation des produits et des fournisseurs
- L'exportation XML des produits s'interrompait avec un code HTTP 500 dès qu'un article ne figurait pas encore dans l'index de recherche rapide. Ces articles sont désormais exportés normalement ; l'exportation JSON n'était pas concernée.
- L’importation de produits au format XML synchronise désormais le nœud «
suppliers» au lieu de supprimer puis de recréer les fournisseurs. La référence fournisseur des fournisseurs permanents est conservée. À partir de la version 4.9.139 de la boutique.
v2.122.4
30 septembre 2026Fonctionnalités et tickets
- Caractéristiques : «
options[].cost» est désormais un autre nom pour «ext_cost». Auparavant, un prix d’achat écrit de cette manière aboutissait à un emplacement que ni la page produit, ni la page de paiement, ni l’éditeur ne lisaient. Si les deux sont envoyés, c’est «ext_cost» qui s’applique. Le prix d’achat et le prix de vente conseillé sont vérifiés en tant que montants ; les valeurs non valides déclenchent l’avertissement «OPTION_META_INVALID». - Tickets :
DELETE /ticketssupprime désormais toutes les données associées au ticket, telles que les responsables, les abonnés, les liens vers les rendez-vous et les projets. À partir de la version 4.9.135 de la boutique.
v2.122.3
30 septembre 2026Création de commandes : prix en cas de calcul brut
orders:writeavectax_flag = 1: les prix calculés par la boutique (recalc) et les frais de port provenant decompute_shippingsont des montants nets. Jusqu’à présent, ils étaient comptabilisés comme des montants bruts, la taxe n’apparaissant pas dans le total. Désormais, ils sont extrapolés. Les prix que vous envoyez vous-même restent bruts, comme auparavant.- Si vous avez adapté
expected_totalà un montant trop bas, vous recevez désormais l'avertissementTOTAL_DRIFT(avecstrict_totalsHTTP 422). - Les suppléments de formule des caractéristiques standard (
apply_default_attributes) sont calculés comme sur la page du produit. Jusqu’à présent, une formule donnait 0 €. Les formules que seule la page du produit peut évaluer génèrent l’avertissement «DEFAULT_ATTRIBUTE_FORMULA». À partir de la version 4.9.134 de la boutique.
v2.122.2
29 septembre 2026Clients : modification partielle des adresses sans que le pays ne revienne à sa valeur initiale
PUT /Import/JSON/customersavecaddresses[]etaddress_book_id(ou l’objetaddress), seuls les champs envoyés sont désormais mis à jour. Jusqu’à présent, toute mise à jour sans indication de pays définissait le pays sur celui de la boutique et la zone sur 0. Une simple mise à jour de la rue transformait ainsi une adresse autrichienne en une adresse allemande.- Le pays et la zone ne changent que si vous les transmettez. En cas de pays inconnu, la réponse signale l’avertissement
ADDRESS_COUNTRY. Une mise à jour conserve alors le pays enregistré, tandis qu’une nouvelle adresse reçoit, comme auparavant, le pays de la boutique. - Autre correction : les apostrophes étaient enregistrées avec une barre oblique inversée, et les valeurs trop longues étaient tronquées octet par octet sans avertissement. Désormais, la troncature s’effectue caractère par caractère, avec l’avertissement «
ADDRESS_TRUNCATED». Les chiffres dans «entry_country» ne sont pas considérés comme des identifiants de pays. - Boutiques utilisant une version antérieure : veillez à toujours indiquer le pays lors des mises à jour d’adresse. À partir de la version 4.9.132 de Shop.
v2.122.1
27 septembre 2026Sécurité : exportation des clients et des commandes sans données de mot de passe
- Les exportations
/customerset/orders(JSON et XML) ne fournissent plus le hachage du mot de passe ni les jetons pour la réinitialisation du mot de passe et la suppression du compte :customers_password,customers_password_request,customers_password_request_timeetcustomers_hashsont supprimés sans remplacement. - De plus, l'enregistrement client ne contient plus de «
iban» ni de «bic». Dans l'enregistrement de commande, ces deux champs sont conservés. À partir de la version 4.9.123 de la boutique.
v2.121.0
19 septembre 2026L'importation des actualités crée les langues manquantes
POST /Import/JSON/newsdeskcomplète, lors de la création, chaque langue active pour laquelle aucun bloc spécifique n’a été envoyé, à partir de la langue principale (le bloc «de», ou sinon le premier bloc envoyé). Si la traduction DeepL est configurée, elle traduit ces langues lors de la prochaine exécution. Jusqu’à présent, un article créé uniquement avec «de» restait définitivement monolingue.- Les textes modifiés au format imbriqué «
languages» sont désormais également retraduits. À partir de la version 4.9.106 de la boutique.
Les numéros de version 2.119.1, 2.121.1 et 2.122.0 concernent des points de terminaison internes ; la version 2.120.0 n’a pas encore été publiée.
v2.119.0
18 septembre 2026API REST : toujours avec un jeton, avec en option une restriction supplémentaire aux adresses fixes
- Important : l’autorisation IP de l’interface XML (
XML_PORT_IP_FILTER) ne donne plus accès à l’API JSON/REST. REST exige toujours un jeton OAuth2, et ce sont ses champs d’application qui s’appliquent. Un client qui utilisait jusqu’à présent REST sans jeton, uniquement via une adresse autorisée, recevra le message «401» avec «reason: deny_token_required». - Le paramètre
XOPORT_REST_IP_LISTconstitue une nouvelle mesure de sécurité supplémentaire. S’il est renseigné, toute requête doit provenir d’une adresse figurant dans la liste et comporter un jeton valide, faute de quoi la réponse403s’affiche avecreason: deny_ip_not_listed. - Si l’API rejette une requête, elle indique le motif dans le champ «
reason» et dans l’en-tête «X-XoPort-Deny-Reason». L’interface XML reste inchangée. À partir de la version 4.9.83 de la boutique.
v2.118.1
17 septembre 2026Tickets : plus d’avertissement erroné pour les rendez-vous liés
linked_appointmentsLes champsPOST/PUT /Import/JSON/ticketsgénéraient en outre l'avertissement «UNKNOWN_FIELD» (« will be ignored »), bien que les rendez-vous soient créés depuis la version v2.43.0. Cet avertissement a été supprimé, mais le traitement reste inchangé. À partir de la version 4.9.75 de Shop.
v2.118.0
17 septembre 2026Tickets : demande de traitement
- Le nouveau point de terminaison
PUT /Import/JSON/ticket_claims(portéetickets:write) indique qui travaille actuellement sur un ticket. Champs obligatoires :ticket_id,admin_idetstate(claimedoureleased), champs facultatifs :ttl_minutes(valeur par défaut 60, de 5 à 240),labeletforce. - Résultat par enregistrement dans
records[].status:claimed,refreshed,taken_over,released,unchangedouconflict. ⚠ Un conflit est représenté parfailed. GET /ticketsetGET /ticket/{id}renvoient les nouveaux champsclaimetedit_lock(le ticket est actuellement ouvert dans le backend), ainsi quenulldans tous les cas où aucune information n’est disponible.- Une réponse publique (via l’API ou dans le backend) et le passage à un statut « fermé » valident automatiquement la réclamation, contrairement à une note interne. La réclamation est une remarque, pas un blocage, et ne modifie ni
ticket_date_last_modifiedni l’historique. À partir de la version 4.9.73 de Shop. - Les numéros de version v2.116.0 et v2.117.0 font partie des nouveautés qui seront disponibles avec la prochaine mise à jour de fonctionnalités ; ils seront alors ajoutés ici.
v2.115.0
15 septembre 2026Les importateurs XML vérifient le fichier de flux lors du chargement
- Si un fichier contient des caractères interdits par XML 1.0 (par exemple, des caractères de contrôle dans les textes descriptifs), les huit importateurs XML suppriment ces caractères et traitent le fichier. Jusqu’à présent, un tel fichier renvoyait 0 enregistrement, était néanmoins archivé et la réponse indiquait que l’opération avait réussi.
- Si un fichier reste illisible après cette opération, il est déplacé vers
xoport/xml/import/error/au lieu d’être archivé, puis supprimé à l’issue du délai de conservation, tout comme l’archive. - Nouveaux champs de réponse :
outcome(ok,partial,failed),files.failedetwarnings.invalid_xml_chars_removed.files.processed.filenamesne mentionne plus les fichiers rejetés. - ⚠ Si tous les fichiers d'un cycle échouent, l'importation renvoie «
"state": "error"» et le code HTTP 422. Les interfaces qui analysent le statut HTTP détectent ainsi un tel échec pour la première fois ; vous pouvez identifier les fichiers refusés individuellement grâce à «outcome: "partial"». À partir de la version 4.9.65 de Shop.
v2.114.0
14 septembre 2026Produits exclus des bons de réduction
GET /couponsetGET /coupon/{id}fournissent le nouveau champrestrictions.excluded_products: les identifiants de produits qui ne bénéficient jamais d’une réduction via ce bon de réduction.- Cette exclusion s’applique en plus de toutes les autres restrictions et prévaut sur
restrictions.products. Un article principal exclu inclut ses variantes, tandis qu’une variante exclue n’inclut qu’elle-même. - Les coupons sans exclusion renvoient une liste vide
[].
v2.113.1
14 septembre 2026Coupons : correction de restrict_mode
- ⚠ Jusqu’à présent,
restrict_modeétait exporté à l’envers. La correction est la suivante :allow_only= uniquement les articles des catégories listées,deny= tous sauf ceux-ci, sauf si l’article se trouve également dans une catégorie non listée, désormaisdeny_strict= tous sauf les articles se trouvant dans une catégorie listée quelconque. - Ce champ décrit exclusivement
restrictions.categories.restrictions.productsetrestrictions.manufacturerssont toujours des listes positives ; si la liste des produits est renseignée, les catégories et les fabricants ne sont pas pris en compte. - Si vous exploitez ce champ depuis la version v2.102.0, veuillez vérifier votre affectation.
v2.113.0
13 septembre 2026Attribution d’un numéro de facture via l’interface
- Nouveau champ «
assign_invoice_number» surPOSTetPUT /Import/JSON/orders: avec «true», la boutique attribue le prochain numéro de sa série de numéros de facture. Le numéro lui-même ne peut pas être défini et est ensuite immuable. - La réponse indique «
invoice_number_assigned» ; en cas de succès, elle renvoie également «invoice_id_individuell» et «invoice_date». Dans le cas contraire, «invoice_number_reason» indique la raison (mode_disabled,already_assigned,locked), accompagnée de l'avertissement «INVOICE_NUMBER_NOT_ASSIGNED». - Les attributions simultanées sont bloquées les unes par rapport aux autres. Si vous obtenez le message «
locked», cela signifie que la boutique a délibérément choisi de ne pas attribuer de numéro plutôt que d’en attribuer un en double ; dans ce cas, veuillez réitérer votre requête.
v2.112.0
13 septembre 2026Nouvelles catégories avec les paramètres du masque d’administration
- ⚠ Si vous créez une catégorie sans
sitemapoushop_ids, les mêmes valeurs que celles du masque d’administration s’appliquent désormais :sitemap = 1et toutes les boutiques sous forme de liste complète. Jusqu’à présent, les paramètres des colonnes s’appliquaient (pas de plan du site, pas d’affectation de boutique). - L'avertissement
CATEGORY_DEFAULTS_APPLIEDindique les valeurs définies. Les mises à jour des catégories existantes ne sont pas concernées.
v2.111.0
13 septembre 2026Supprimer les vidéos et les numéros d'expédition
videos[]: supprimer des entrées individuelles avec_action: "delete", ou utiliservideos_replace: truepour reprendre la liste envoyée dans son intégralité (uniquement sur demande expresse). Le fichier vidéo lui-même est conservé, seule l'affectation est supprimée.trackings[]:_action: "delete"viaid_trackingouservice_provideretcode. Un numéro d’expédition peut ainsi être supprimé et recréé en une seule opération.- Dans les deux cas, vérifiez que l’entrée correspond bien au produit ou à la commande indiqués.
v2.110.0
13 septembre 2026Caractéristiques d'un poste de commande existant
products_mode: "update"accepte désormaisattributes. La liste envoyée remplace intégralement les caractéristiques du poste, tandis que[]les supprime toutes.- Une majoration différente ne modifie pas le prix du poste – l’interface affiche un avertissement dans ce cas. Si le prix doit être modifié, annulez le poste et rajoutez-le.
- La modification est bloquée pour les commandes déjà facturées, car les caractéristiques figurent sur la facture et le bon de livraison.
v2.109.0
13 septembre 2026Lecture et activation des fichiers CSV/XLS
- Nouveau :
GET /Export/JSON/porters,/porter/{id}etPUT /Import/JSON/portersavec les portéesporters:readetporters:write. activedéfinit l'état (true= actif par la suite) au lieu de le basculer. Sansactive, l'appel est rejeté. Lors de la désactivation, la boutique supprime le fichier d'exportation généré, comme dans le backend.- L'appel unique fournit, à l'adresse
columns, le mappage complet des colonnes du Porter.
v2.108.0
13 septembre 2026Lire et modifier les paramètres
- Nouveau :
GET /Export/JSON/configurationetPUT /Import/JSON/configurationavec les scopesconfiguration:readetconfiguration:write. - ⚠ Seules les clés que l’administrateur partage dans
XOPORT_CONFIG_API_KEYSsont visibles – par défaut, la liste est vide. Les identifiants d’accès, les paramètres de licence et de session restent verrouillés même lorsqu’ils sont partagés. - Seules les clés existantes peuvent être modifiées ; chaque modification est consignée. L'avertissement
SHOP_OVERRIDE_ACTIVEsignale un remplacement de domaine qui remplace la valeur de base modifiée.
v2.107.0
13 septembre 2026Responsable dans l’historique de la commande
user_idd’une commandePUTindique le responsable de l’opération dans l’entrée de l’historique. Seul un identifiant de responsable existant est repris.customer_notifiedLe message continue d’être rédigé, mais l’interface signale, viaNO_MAIL_SENT, qu’elle n’envoie pas elle-même d’e-mail de statut.
v2.106.0
13 septembre 2026Téléchargement de vidéos de produits, d’images d’options et de sous-dossiers
- Téléchargement de médias via
entity_type: "product_video"(jusqu’à 100 Mo) etentity_type: "option"pour les images d’options. subfolderEnregistre les images dans un sous-dossier (un niveau, minuscules, chiffres,_et-).- L'extension de fichier est déterminée à partir du type de fichier détecté, et non à partir du nom de fichier envoyé.
v2.105.0
13 septembre 2026L'exportation des produits peut être renvoyée
- 68 champs de produit supplémentaires sont modifiables, notamment les prix dégressifs avec seuils de quantité, le commutateur eBay
ebay_allowed(module eBay classique), le blocage Amazon Payamazon_allowed, la classification FSK 18, les marchandises soumises à des restrictions, le prix de vente conseillé, les points bonus et la date d’acquisition. - 14 champs en lecture seule sont signalés comme
READONLY_FIELDau lieu d’être rejetés sans commentaire. - ⚠ Les valeurs non valides (valeur de sélection inconnue, texte trop long, chiffre illisible) rejettent l’enregistrement au lieu de l’écrire à moitié. Les champs Oui/Non envoyés vides restent inchangés.
- Correction : il était initialement écrit ici « les boutons de la place de marché ».
amazon_allowedn’est toutefois pas un bouton de la place de marché, mais le verrouillage d’Amazon Pay :1masque les boutons Express d’Amazon Pay tant que l’article se trouve dans le panier. La signification des champs est indiquée sous « Produits », section « Autres champs de produit ».
v2.104.0
13 septembre 2026Les images de produit remplacées reçoivent de nouvelles vignettes
- Si une image est remplacée sous le même nom de fichier, la boutique supprime les vignettes associées, quel que soit leur format. La réponse indique
thumbnails_removedetreplaced_existing. - Les entrées dans
videos[]sont vérifiées pour détecter d’éventuels noms de champs inconnus ; avec?_strict=true, une faute de frappe entraîne une erreur HTTP 400.
v2.103.0
13 septembre 2026Services de gestion des tickets
- Nouveau :
GET /Export/JSON/ticket_departments(?active=),/ticket_department/{id},POST/PUT /Import/JSON/ticket_departmentsetDELETE /Delete/JSON/ticket_department/{id}. - Les sections sont multilingues ; les langues vides reprennent le nom de la langue par défaut.
- Si un ticket est encore attribué à un service, la suppression renvoie la réponse «
409 DEPARTMENT_IN_USE». «?reassign_to={id}» réattribue d’abord les tickets, tandis que «?force=1» procède quand même à la suppression.
v2.102.0
13 septembre 2026Bons d'achat et coupons au format JSON
- Nouveau :
GET /Export/JSON/couponset/coupon/{id}avec les filtres?code=,?type=,?active=,?kind=et?valid_on=. - Les restrictions sont fournies sous forme de listes d’identifiants, ainsi que les champs lisibles
restrict_modeetis_credit_voucher. La valeur «0» pour les limites d’utilisation signifie « illimité ». - Corrigé : le nom et la description d’un coupon manquaient jusqu’à présent dans l’exportation.
v2.101.0
13 septembre 2026L'exportation XML vérifie les autorisations
- ⚠ Un jeton OAuth2 à portée restreinte reçoit désormais, dans l’export XML, la mention «
403» pour les domaines sans autorisation :customers:read,orders:read(également pour les bons d’achat),products:read,categories:read,manufacturers:read. - Les connexions via AppKey ou l'autorisation par adresse IP ne sont pas concernées.
v2.100.0
13 septembre 2026Configuration des filtres des pages de catégories
- Nouveau :
GET /Export/JSON/products_filterset/products_filter/{fid}avec?options_id=et?categories_id=– quels filtres une page de catégorie propose. - Remarque : la version 2.100.0 succède à la version 2.99.0. Comparez les versions à l'aide de
version_compare(), et non sous forme de nombre décimal.
v2.99.0
13 septembre 2026Exportation de clients avec filtres et pagination
- Nouveaux filtres sur
/customers:customers_id,customers_group_id,language_id,email,lastname,company,customers_id_extern, les filtres de préfixeemail_prefix,lastname_prefix,company_prefixainsi quepurchased_without_account,sort,orderetpage. - Les bases de données clients volumineuses sont parcourues au fur et à mesure plutôt que chargées dans leur intégralité.
- Une valeur de filtre invalide entraîne l'erreur «
400 INVALID_FILTER_VALUE» au lieu d'être simplement ignorée.
v2.98.0
12 septembre 2026Numéros d’expédition, demande d’évaluation, champs de position
trackings(au pluriel, comme dans l’export) sont pris en compte. Les numéros d’expédition en double sont ignorés et signalés ; un lien manquant est complété à partir du prestataire de services d’expédition.rating_mailest modifiable.products_mode: "update"Modifie les champs des lignes existantes (prix d'achat, nom, référence, EAN, unité, profil d'expédition, champs de date). Les quantités, les prix et le taux d'imposition sont rejetés.
v2.97.0
12 septembre 2026Supprimer les pièces jointes du ticket, renvoyer l'e-mail
- Nouveau :
DELETE /Delete/JSON/ticket_attachment/{tshid}?filename=. notify_history_idL'adressePUT /Import/JSON/ticketsrenvoie l'e-mail de réponse correspondant à une entrée existante de l'historique, sans en créer une nouvelle.apply_value_defaultsReprend les valeurs par défaut de l’option lors de la première attribution d’une caractéristique (sur demande expresse, car les valeurs par défaut peuvent entraîner un supplément).
v2.96.0
12 septembre 2026Caractéristiques et valeurs d’option en tant que points de terminaison distincts
- Nouveau :
GET /Export/JSON/products_options,/products_option/{id},/products_options_valuesainsi quePOST/PUT /Import/JSON/products_options. values[]Cette liste n'est pas exhaustive : seules les entrées portant la valeur «_action: "delete"» sont supprimées ; «_action: "attach"» partage une valeur existante.- ⚠ Une
option_idinconnue lors de l’importation de produits est désormais rejetée avec le message «OPTION_NOT_FOUND», au lieu de créer silencieusement une caractéristique.
v2.95.0
12 septembre 2026Supprimer des entrées individuelles de l'historique
- Nouveau : «
DELETE /Delete/JSON/order_status_history/{id}» et «DELETE /Delete/JSON/ticket_status_history/{id}». Le statut de la commande ou du ticket est mis à jour comme indiqué dans le masque. - L'entrée la plus ancienne d'une commande est protégée (
409 FIRST_HISTORY_ENTRY).
v2.94.0
12 septembre 2026Profils de délais de livraison
- Nouveau :
/shipping_profileset/shipping_profile/{id}en lecture et en écriture, avec des niveaux, des plages de délais de livraison et des textes personnalisés par langue. - Au niveau du produit, l’exportation fournit en outre
shipping_profile_effective,_name,_stepet_text.
v2.93.0
12 septembre 2026Recherche rapide et adressage via l’ID du produit
- Les produits créés ou modifiés via l’interface sont intégrés à la recherche rapide. L’exportation affiche l’état de l’index par langue à l’adresse
quicksearch. - Corrigé : une requête
PUTavecproducts_idpouvait se solder par une erreur HTTP 500, et les modifications d’adresse ne généraient pas de redirection par ce biais.
v2.92.0
12 septembre 2026Règles d'options du configurateur
options_rules[]sur le produit, en lecture et en écriture. Si le champ est absent, les règles existantes restent inchangées.- L'exhaustivité des blocs de règles actifs est vérifiée avant l'écriture ; sans la licence correspondante, l'opération est refusée.
v2.91.0
12 septembre 2026Historique des statuts et textes des justificatifs pour chaque commande
- L'exportation des commandes fournit
status_history[]avec toutes les entrées d'historique. indiv_text0Les champs « bisindiv_text4» (textes de remplacement par document) ainsi que «indiv_rg» et «indiv_ls» (noms de fichiers des PDF enregistrés) sont modifiables.- Les avertissements d'un fichier « commande » (
PUT) s'affichent désormais au niveau de l'entrée correspondante dansrecords[].
v2.90.0
12 septembre 2026Classes d'imposition et détails des tickets
- Nouveau :
GET /Export/JSON/tax_classeset/tax_class/{id}indiquent les taux d’imposition par zone fiscale. - L'historique des tickets fournit l'ID de message des e-mails reçus et
ticket_event_type. - Corrigé : une simple modification du titre de la vidéo entraînait une erreur HTTP 500.
v2.89.0
12 septembre 2026Les succès partiels sont signalés
- Corrigé : lors de l’ajout de lignes, un code langue pouvait apparaître sur la facture à la place du titre fiscal.
- Sans
admin_idvalide, aucune entrée n’est désormais créée dans l’historique des tickets. outcomeSignalepartiallorsqu’une partie de la commande a été refusée. Autre nouveauté :?order_id=est désormais envoyé à/tickets.
v2.88.0
12 septembre 2026Onglets « Produits » multilingues
tabsest prise en charge dans les formats plat, imbriqué par langue et d’exportation ; l’exportation fournit un bloclanguagespar onglet.- Les nouvelles catégories sans
sitemap/shop_idss'affichent avecCATEGORY_DEFAULTS_APPLIED.
v2.87.0
12 septembre 2026Les frais et la référence de commande sont modifiables
handling_fee,transaction_fee,selling_fee,other_feeetpo_numberpeuvent être définis viaPOSTetPUT.- Les montants hors de la plage de valeurs et les références trop longues sont rejetés plutôt que raccourcis. Le filtre
?po_number=sur/ordersest une nouveauté.
v2.86.0
12 septembre 2026Parcourir et trier
?sort=et «?order=» vers «/orders» et «/products» ; «?page=» a été mis en œuvre et est confirmé sous la forme «stats.page».pageL'utilisation conjointe deoffsetentraîne une erreur. Une spécification tronquée delimitrenvoieLIMIT_CAPPED.
v2.85.0
12 septembre 2026Prix spéciaux entièrement inclus dans l'exportation
- Les prix spéciaux sans étiquette manquaient jusqu’à présent dans l’exportation. Désormais, tous les champs sont inclus, y compris le groupe de clients, la période, l’étiquette et le type.
- Les produits nouvellement créés portent la mention «
products_last_modified» et apparaissent ainsi dans le filtre de modification.
v2.84.0
12 septembre 2026Les verrous de catégorie sont désormais modifiables
subs_blocket «tree_block» sont modifiables. ⚠ «subs_block» s'applique aux redirections et au plan du site de toute la branche de catégories.
v2.83.0
12 septembre 2026Tous les points de terminaison d'exportation vérifient leurs filtres
- Les filtres inconnus sont signalés à chaque point de terminaison d'exportation par
UNKNOWN_FILTER; avec?_strict=true, l'appel est interrompu.
v2.82.0
12 septembre 2026Le fabricant, via le nom
manufacturers_nameet le bloc « Fabricant » de l’exportation sont résolus. Les noms inconnus ou ambigus sont rejetés, et non créés.- Documentation sur les données supprimées par
DELETE /product– souvent,products_status = 0est le meilleur choix.
v2.81.0
12 septembre 2026Les prix spéciaux et les champs supplémentaires peuvent être renvoyés
specialest accepté sous forme de liste ou d’objet unique,slp_valueen tant que nom d’étiquette.extra_fieldsApparaît sous forme de liste vide même en l'absence d'entrées.
v2.80.0
12 septembre 2026Renvoyer sans perte de données
- Corrigé : les affectations de catégories dans le formulaire d’exportation déplaçaient les produits vers la catégorie 1.
- Les listes d'images sont d'abord vérifiées, puis enregistrées ; une image principale reste l'image principale.
v2.79.0
12 septembre 2026Mise à jour partielle des catégories
- Un «
PUT» de catégorie n’a plus besoin du bloc de langue. categories_mode: "append"Ajout d'affectations au produit ; la synchronisation complète signale les affectations supprimées viaCATEGORY_ASSIGNMENTS_REPLACED.
v2.78.0
12 septembre 2026Attribution d'un ticket à un client via PUT
ticket_customers_orders_id,ticket_customers_id,ticket_customers_nameetticket_customers_emailsont enregistrées dans la table «PUT». L'adresse e-mail ne peut pas être laissée vide.
v2.77.0
12 septembre 2026Tout ou rien lors de l'importation
?_strict=trueRejette complètement les produits, catégories, clients et commandes comportant des champs inconnus (400 UNKNOWN_FIELD) avant que quoi que ce soit ne soit enregistré.
v2.76.0
12 septembre 2026Accéder aux produits via leur ID
- Il suffit d'un
PUTavecproducts_id. Les références d'articles utilisées plusieurs fois sont rejetées au lieu de correspondre à un article quelconque.
v2.75.0
12 septembre 2026Filtres de produits précis
- Nouveau :
products_modeletproducts_eancomme filtres exacts,products_idcomme filtre ;manufacturers_idfonctionne désormais. - Si un identifiant unique dans un chemin pluriel renvoie plusieurs enregistrements, cela est signalé par
RANGE_START_NOT_SINGLE_RECORD.
v2.74.0
12 septembre 2026Tickets : pas d’envoi en cas de pièce jointe manquante
- Si une pièce jointe est rejetée, aucun e-mail n’est envoyé au client ; le commentaire reste enregistré.
- Nouveau champ de réponse «
outcome» (ok,partial,failed) comme critère de réussite fiable.
v2.73.0
12 septembre 2026Chiffres dans le JSON sans perte silencieuse de données
- Si la reconnaissance des nombres convertit des valeurs (par exemple, des zéros non significatifs), cela est signalé par «
NUMERIC_CHECK_APPLIED». «?numeric_check=false» renvoie ces valeurs telles quelles sous forme de texte.
v2.72.0
12 septembre 2026Récupération de documents sans effet secondaire
- Corrigé : la récupération d’une correction de facture via
order_documentpouvait générer un numéro de correction. En l’absence de correction existante, le point de terminaison répond désormais avec409. - Les champs non renseignés d’une commande
PUTrenvoientFIELD_IGNORED_ON_UPDATE. Le mode de paiement, l’adresse de facturation et l’adresse de livraison peuvent être modifiés viaPUT.
v2.71.0
12 septembre 2026Lecture et écriture complètes des caractéristiques
- ⚠ Les affectations de caractéristiques existantes sont mises à jour au lieu d’être ignorées ; les champs non envoyés restent inchangés.
options_replaceComparaison par différence : les écrans d’options, le facteur de prix de base et le prix d’achat ne sont plus perdus. La commande_action: "delete"supprime une attribution unique.- Les caractéristiques nouvellement créées sont signalées par «
OPTION_CREATED» ; «options_strict_names» rejette quant à lui les noms inconnus.
v2.70.0
12 septembre 2026La suppression nécessite désormais la méthode DELETE
- ⚠ Veuillez vérifier votre connexion. Les points de terminaison sous
Delete/JSON/n’acceptent désormais plus que la méthode HTTPDELETE. Toute autre méthode entraîne une réponse de l’interface avec405 METHOD_NOT_ALLOWEDet le champ d’en-têteAllow: DELETE– et ce, avant que quoi que ce soit ne se produise. - Pourquoi cela était-il nécessaire ? Jusqu’à présent, l’interface ne vérifiait pas du tout la méthode à ce stade. Un simple appel de l’adresse dans un navigateur, un aperçu de lien ou un robot de moteur de recherche pouvait ainsi supprimer un enregistrement. Il suffisait qu’un jeton d’accès apparaisse une seule fois dans une adresse.
- Conséquences pratiques : probablement aucune. Nous avons analysé les journaux d'accès avant la mise à jour : toutes les requêtes de suppression observées utilisaient déjà
DELETE. En revanche, si votre programme utiliseGETouPOST, veuillez le mettre à jour.
Les messages d’erreur sont désormais exploitables
- Les adresses inconnues, les plages de numéros non valides et les points de terminaison inexistants renvoient désormais une réponse au format JSON accompagnée du code d'état HTTP approprié (
404,400,501) au lieu d'une simple ligne de texte. Auparavant, le serveur renvoyait le code200selon le mode de fonctionnement de l’environnement PHP – un traitement des erreurs analysant le code d’état considérait donc l’appel comme ayant abouti. - Les objets d'erreur suivent la structure habituelle :
error.code(NOT_FOUND,INVALID_RANGE,NOT_IMPLEMENTED) eterror.message.
v2.69.0
7 septembre 2026Les destinataires en copie (CC/BCC) peuvent désormais écrire
- Nouveau champ «
receivers» surPOST/PUT /ticket(s):{ mode, cc, bcc }. Jusqu’à présent, les destinataires étaient en lecture seule – leur gestion s’effectuait exclusivement dans l’interface de la boutique. - Le mode «
add» (par défaut) ajoute des destinataires, «replace» remplace uniquement les listes fournies, tandis que «remove» supprime des adresses individuelles. Les adresses sont vérifiées comme dans le backend ; une liste ne contenant que des adresses non valides laisse la liste inchangée – une faute de frappe ne doit pas vider la liste des destinataires. - L'opération s'effectue avant l'ajout d'un commentaire et l'envoi de l'e-mail issus de la même requête : « Compléter l'adresse et répondre » s'effectue ainsi en une seule étape.
v2.68.0
31 août 2026Catégorie principale par produit
- Nouveau champ «
main_category_id» dans l’entité produit. Il détermine laquelle, parmi les différentes attributions de catégorie, fournit le chemin de catégorie dans l’adresse, l’adresse canonique, l’entrée dans le plan du site et l’indication de catégorie dans les flux du portail de prix. - ⚠ La sémantique d’importation s’écarte délibérément de
categories: si le champ est absent, le stock reste inchangé. Sinon, tout programme existant qui met à jour les produits supprimerait la catégorie principale lors de sa première exécution. La valeur0annule cette règle. - Une catégorie qui n’est pas du tout attribuée au produit est rejetée et signalée – une importation ne doit pas générer d’attribution vide.
v2.67.0
26 août 2026Le type de garantie peut désormais être importé
- Nouveau champ «
warranty_type» dans l’importation de produits. Les valeurs autorisées sont «physical» et «digital» ; l’orthographe est corrigée. La sémantique habituelle de «array_key_exists» s’applique : si la clé est absente, la colonne reste inchangée ; une chaîne vide la vide. - L’exportation a toujours fourni ce champ – seule l’importation ne le reconnaissait pas. Un cycle complet « exporter, modifier, réécrire » était donc impossible. La version 2.63.0 avait comblé cette lacune pour les champs de stock.
- ⚠ Une valeur invalide est rejetée, elle n’est pas corrigée. Vous recevez un avertissement dans
warnings[], la valeur existante est conservée. C’est intentionnel : ce champ détermine en partie si la boutique traite un article comme un produit physique ou comme un contenu numérique – et donc les informations obligatoires relatives à la garantie.
Sans contrat API, mais corrigé dans la même opération
- Importation CSV :
warranty_periodest désormais vérifié par rapport aux valeurs autorisées. Jusqu’à présent, un texte libre était simplement converti en minuscules puis enregistré – modifié, mais tout aussi inutilisable. Il en va de même pour une garantie fabricant non valide, qui était auparavant discrètement effacée, supprimant ainsi une information correctement renseignée. - Importation de produits au format XML : prend en charge pour la première fois les six champs relatifs à la garantie légale et à la garantie commerciale. Si votre flux ne les fournit pas, ils restent inchangés – un flux purement consacré aux stocks ou aux prix n’y change rien.
v2.66.1
25 août 2026Les rendez-vous supprimés disparaissent de l’exportation des tickets
- L’exportation des tickets continuait de fournir des rendez-vous supprimés de manière temporaire. Quiconque vérifiait une suppression via le ticket pensait qu’elle avait échoué. Le champ concerné était «
linked_appointments[]» de «GET /Export/JSON/tickets». - La cause était une omission, et non une faute de frappe. Ce bloc provient de la version 2.11.0 – quatre mois avant l’introduction de la suppression temporaire des rendez-vous (v2.44.0) – et n’a jamais été mis à jour avec le filtre lors de la mise à jour. La suppression temporaire laisse délibérément la ligne de lien en place (restauration et « pierre tombale » CalDAV) ; c’est pourquoi chaque lecteur doit filtrer lui-même les données. Le formulaire de ticket et le widget de rendez-vous dans le backend le faisaient depuis toujours – l’API était donc en contradiction avec la propre interface de cette même boutique.
- ⚠ Changement de comportement sans adaptation de votre part :
linked_appointments[]peut devenir plus court, et des entrées peuvent disparaître entre deux consultations, sans que rien n’ait changé au niveau du ticket. Il n’y a pas de « pierres tombales » sur cette branche. - Les « pierres tombales » existent toujours – et sont plus complètes :
GET /Export/JSON/appointments?ticket_id={id}&include_deleted=1fournitdeleted_atet les descriptions dans toutes les langues ; pour la récupération groupée,?include_deleted=1&last_modified=…ainsi querelationships[]. La ressource « tickets » ne reçoit délibérément pas deinclude_deleted: le nom serait ambigu à cet endroit, car les tickets ne connaissent pas de « soft-delete ». - Même cause corrigée dans le backend : huit requêtes reliaient des projets, des commandes et des tickets via des rendez-vous, sans vérifier la table des rendez-vous. Un rendez-vous supprimé continuait de créer un lien, et les liens vers les rendez-vous générés à partir de celui-ci ne menaient nulle part.
v2.66.0
24 août 2026Blocage d’importation pour la classe d’imposition
- Nouveau type de blocage «
tax» dans «import_blocks». Cette modification a été motivée par le prix fixe du livre : le blocage du prix à lui seul ne préserve pas un prix de vente fixe ; si le prix net reste inchangé et que la classe fiscale change lors de l’importation, le prix brutmodifie malgré tout, et c’est précisément cette valeur qui est fixe. Pour les produits à prix fixe, il faut donc toujours l’utiliser conjointement avecprice. - Ce type s’applique de manière globale (sans référence à la langue) et est pris en compte par tous les importateurs de produits. Lors de l’exportation, il apparaît automatiquement, car «
import_blocks[]» est indépendant du type. - Parallèlement, dans le backend : le masque de l’article comporte désormais un onglet « Gestion des marchandises » au lieu de deux onglets qui contrôlaient les mêmes verrouillages et s’effaçaient mutuellement lors de l’enregistrement.
v2.65.0
24 août 2026Filtres côté serveur pour la liste des produits
- Jusqu’à présent, il n’existait que
?limitet?offset. Quiconque avait besoin d’un sous-ensemble devait récupérer le catalogue complet page par page – soit 250 requêtes pour 62 000 articles, alors que la base de données répond à cette question en une seule requête. - Nouveaux filtres :
?status=,?tax_class_id=,?categories_id=,?ean_prefix=,?model_prefix=et?last_modified=. Une virgule sépare une liste d’inclusion (100 valeurs au maximum) ; plusieurs filtres sont combinés par un « ET ». Exemple :?ean_prefix=978,979,977&tax_class_id=0,1&status=1permet de trouver tous les articles disponibles à la vente dotés d’un code EAN « livre » qui ne bénéficient pas du taux réduit. - Absence délibérée de l’opérateur « différent de »: l’APIne le reconnaît pour aucune entité. « Tout sauf la classe fiscale 2 » s’écrit sous forme de liste d’inclusion des autres classes ; cela reste indexable, au lieu d’introduire un deuxième langage de requête.
stats.totalindique désormais le nombre de résultats. Auparavant, ce champ affichait toujours le nombre total de produits, quelle que soit la requête –stats.has_moreétait donc incorrect.- Une valeur de filtre invalide génère une erreur (HTTP 400), et non un avertissement. Si le filtre était discrètement ignoré, le catalogue non filtré serait renvoyé – une recherche d’enregistrements erronés afficherait alors « rien trouvé ». Les filtres appliqués à une ressource unique ou à une plage d’identifiants sont rejetés pour la même raison.
include_inactive_productsSans objet. Ce nom faisait partie de la liste des produits d’une catégorie, n’a jamais été pris en compte lors de l’exportation des produits et a été remplacé par?status=. Il génère désormais un avertissement au lieu d’une inefficacité silencieuse.- Schéma : nouvel index sur
products_last_modified(programme d’installation et auto-réparation ; pour les très grands catalogues, c’est le HealthCheck qui le propose à la place) – sans lui, le filtre delta effectuerait un parcours complet de la table.
v2.64.0
24 août 2026Les adresses de livraison peuvent rester vides
- Les colonnes d’adresse d’une commande peuvent désormais contenir la valeur NULL (rue, ville et code postal pour les adresses client, de livraison et de facturation). Les importations depuis les places de marché en deux phases créent les commandes à retirer avant même le paiement – l’adresse n’est alors pas encore disponible et est ajoutée lors de la deuxième récupération.
- L’exportation renvoie «
null» pour ces commandes au lieu d’une chaîne vide – «null» signifie « l’adresse n’est pas encore disponible », tandis qu’une chaîne vide signifie « vide ». La raison sociale, le complément d’adresse et la région ont toujours pu accepter la valeur NULL. - Correction : les indicateurs de divergence entre l’adresse de facturation et l’adresse de livraison effectuent désormais une comparaison qui tolère la valeur NULL. Auparavant, un champ vide les faisait passer à tort à « divergent ».
v2.63.0
17 août 2026Stocks consultables, champs de stock de l’entrepôt principal modifiables
- L’exportation fournit les données «
storages[]» : l’exportation des produits inclut désormais les stocks – pour chaque ligne de stock :storages_id,products_quantity,products_safe_quantity,products_reorder_level,products_storage_textetoptions_id. Jusqu’à la v2.62.0, l’exportation JSON ne les fournissait pas du tout: les stocks étaient modifiables via l’API, mais non lisibles, ce qui rendait tout aller-retour impossible. L'ensemble des champs correspond exactement à l'importation ; les données de stock exportées peuvent donc être réimportées telles quelles. - Si le système de stock étendu est désactivé, la clé est totalement absente (et non sous forme de tableau vide) – cela permet à un client de distinguer « fonction désactivée » de « aucune ligne de stock disponible ». Toutes les lignes de stock du produit sont affichées, y compris celles correspondant à des stocks inactifs.
- Entrepôt principal configurable via l’importation : les champs «
products_reorder_level» et «products_safe_quantity» sont désormais autorisés au niveau supérieur du produit et écrivent dans l’entrepôt principal (la table «products»). L’exportation a toujours fourni ces deux colonnes, mais l’importation les rejetait comme des champs inconnus – il était donc impossible de réimporter un produit exporté sans perte de données. - À ne pas confondre : les champs du même nom dans
storages[]appartiennent à un entrepôt supplémentaire.storages_id: 1correspond déjà au premier entrepôt supplémentaire – l’entrepôt principal ne figure pas dans la liste des entrepôts. - Correction
products_quantity: le stock n’est plus arrondi aux nombres entiers lors de l’importation. La colonne autorise les décimales, et lorsque l’option « Quantités fractionnaires dans le panier » est activée, celles-ci sont techniquement souhaitées (articles vendus au mètre, articles vendus au poids) – jusqu’à présent,0.5devenait0, ce qui signifiait que l’article était « en rupture de stock ». Changement visible pour les interfaces qui transmettent des décimales : la valeur est désormais prise en compte, au lieu de disparaître sans laisser de trace. - Inchangé :
storages[]reste une mise à jour partielle sans synchronisation complète (v2.45.0) ; les lignes de stock non transmises restent inchangées. L’import CSV/XML et l’enregistrement dans le backend continuent d’écrire la ligne de stock complète.
v2.62.0
13 août 2026Label de garantie de l’UE (GARAN) via l’interface
- Nouveaux champs produit :
garan_label_enabled(0/1) active le label de garantie de l’UE conformément au règlement (UE) 2025/1960 – obligatoire à compter du 27 septembre 2026. Pour cela, utilisezgaran_brand(marque différente de celle du catalogue) etgaran_model(identifiant du modèle pour le label) ; une chaîne vide supprime la valeur correspondante. L’identifiant du modèle comporte environ 14 caractères – des valeurs plus longues empêchent l’affichage du label. - L’étiquette a une valeur juridique contraignante : chaque validation via l’interface est consignée. C’est l’exploitant de la boutique qui confirme le respect des conditions préalables, et non l’API.
- Garantie constructeur désormais exprimée en demi-années : «
manufacturer_guarantee_years» est une valeur décimale. Les valeurs comportant une virgule ("2,5") sont acceptées et arrondies au demi-niveau inférieur le plus proche, jamais au niveau supérieur. Attention aux analyseurs syntaxiques stricts : l’exportation fournit désormais «"5.0"» au lieu de «"5"».
v2.61.0
12 août 2026Récupération des documents justificatifs d’une commande
- Nouveau point de terminaison :
GET /Export/JSON/order_document/{orders_id}?type=rgfournit le document final au format JSON avec un PDF encodé en base64. Types de documents disponibles :of(devis),ab(confirmation de commande),rg/rgqr(facture, avec ou sans partie « QR » suisse),ls(bon de livraison),st(annulation),pl(liste de colisage),prg(facture pro forma),dr(attestation de don) etso. Portéeorders:read. - Pourquoi base64 plutôt qu’un flux binaire : le champ s’appelle «
content_base64» – exactement comme pour les pièces jointes aux tickets depuis la version 2.60.0. Cela permet de joindre directement un justificatif à un ticket sans passer par un fichier intermédiaire. - C’est exactement le justificatif du backend qui est généré : le même moteur de rendu que pour les pièces jointes aux e-mails est utilisé, dans un processus distinct et sans session. Si un fichier de facture est enregistré pour une commande, celui-ci est transmis.
- Cas d’erreur évidents : commande inconnue →
404, justificatif de facture sans date de facturation →409, type de justificatif non autorisé →400– dans chaque cas sous forme de JSON propre. - Non inclus : les types
eiv_*(XRechnung, ZUGFeRD) sont délibérément exclus – ils génèrent du XML au lieu d’un PDF.
v2.60.0
11 août 2026Les pièces jointes aux tickets sont désormais modifiables
- Nouveau champ «
attachments[]» : les URLPOSTetPUT /Import/JSON/ticketsacceptent désormais des fichiers – pour chaque entrée, unname(nom de fichier, extension comprise) et uncontent_base64(contenu encodé en Base64). - Comportement antérieur : les pièces jointes étaient uniquement consultables (liste et téléchargement depuis la v2.9.0) ; elles ne pouvaient être ajoutées que via le formulaire du backend. Un ticket créé via l’API restait donc sans pièce jointe – un PDF, un fichier
.emlou une capture d’écran devaient être fournis manuellement par la suite. - Les pièces jointes sont associées à une entrée de l’historique, et non au ticket : sans
ticket_commentsdans la même requête, aucune entrée à laquelle le fichier pourrait être associé n’est créée. Il est alors rejeté avec un message d’erreur au lieu d’être simplement ignoré. - Mêmes règles que dans le backend : liste blanche d’extensions identique, même convention de nommage et déduplication par hachage pour éviter les doublons. Le nom de fichier effectivement attribué figure, pour chaque enregistrement, dans la réponse sous
attachments. La limite maximale par fichier correspond au point de terminaison/media(par défaut 10 Mo). - Tolérance aux erreurs : une extension non autorisée, un Base64 non valide ou un dépassement de la taille limite génèrent une erreur par fichier – la mise à jour du ticket elle-même reste réussie. En cas de réponse publique avec notification, les fichiers sont envoyés via l'e-mail du client.
- Intégrations existantes : elles restent opérationnelles sans modification – le champ est facultatif, l’extension est purement complémentaire. Portée
tickets:write.
Corrections apportées à la documentation
- Correction des champs de commentaire : lors de la création d’un ticket, la page Endpoint mentionnait les champs
initial_commentetinitial_comment_admin_id– ces deux champs n’existent pas dans l’interface. Les champs corrects sontticket_comments(texte du commentaire) etadmin_id. De même, lors de la mise à jour,ticket_commentsest un texte, et non un tableau d’objets. Les utilisateurs qui se sont fiés à l’ancienne description n’ont pas reçu de commentaire – et ne peuvent donc pas non plus ajouter de pièces jointes, car rien ne peut être joint sans entrée dans l’historique. - Réponses publiques : la mention « Les réponses directes aux clients ne sont pas possibles via l’API » était obsolète depuis la version 2.25.0 et a été remplacée. Les indicateurs
is_public_reply,notify_customeretappend_signaturesont désormais décrits dans le tableau des champs. - Aucune modification du code : ces deux points concernent exclusivement la documentation ; le comportement de l’interface reste inchangé.
v2.59.0
6 août 2026Extensions internes
- Aucune modification des points de terminaison documentés : cette version étend exclusivement une interface de support interne de XONIC. Les opérations d’exportation, d’importation et de suppression (DELETE) fonctionnent comme auparavant.
- Intégrations existantes : elles restent opérationnelles sans modification – le numéro de version est simplement incrémenté.
v2.58.0
6 août 2026Groupes de caractéristiques combinés dans l’exportation de produits
- Nouveau champ «
option_groups[]» : les caractéristiques associées à un groupe de caractéristiques dans la boutique (généralement « couleur + taille ») sont désormais fournies par l’exportation de produits – y compris les éléments du groupe dans l’ordre d’affichage et, pour chaque combinaison, la référence, l’EAN, la quantité, le prix et le tri correspondants. - Comportement antérieur : les caractéristiques groupées étaient totalement absentes de l’exportation – sans champ vide ni mention particulière. Seules les caractéristiques non groupées (
options{}) étaient exportées. - Pourquoi deux champs ? Dans le cas d’un groupe de caractéristiques, la référence et l’EAN font partie de la combinaison de valeurs (« noir / L » = un EAN), tandis que dans le cas d’une caractéristique unique, ils correspondent à une valeur unique.
options{}reste donc inchangé – il s’agit d’une extension purement additive. - Inchangé : les exportateurs XML et CSV continuent de n'exporter que des caractéristiques non regroupées. L'importation continue d'attendre le format plat
options[].
v2.57.1
22 juillet 2026Correction d’un bug : prix spécifiques au client dans l’importation de produits au format XML
- Importation de produits au format XML : le bloc «
customers» situé dansgroups(prix spécifiques par client et par produit) était ignoré lors de la lecture et n’était jamais enregistré dans la base de données ; les entrées sont désormais importées correctement. L’affectation des clients s’effectue viaid(ID client de la boutique) ouexternal(numéro de client WaWi) ; les numéros de client inconnus sont ignorés. - Règles claires pour les entrées incomplètes :
price 0sans prix échelonnés ne crée pas de ligne (Supprimer = omettre l’entrée – l’importation reflète intégralement la liste des prix clients par produit) ; lesquantity_blocks/min_quantitymanquants sont préremplis avec la valeur 1, comme lors de l’importation REST.
v2.57.0
18 juillet 2026Remises clients et prix personnalisés
- Clients : nouveau champ «
discounts[]» – gérer les remises clients (le champ « Remises » de la gestion des clients) via l’API. Sémantique « replace-on-present » : si le champ contient des entrées, les remises existantes du client sont entièrement remplacées ; un «[]» vide supprime toutes les remises ; si le champ est vide, les remises restent inchangées. L’exportation « Customers » fournit désormais «discounts» (aller-retour). - Importation des produits : nouveau champ
customers_prices[]– prix personnalisés par client, y compris les prix échelonnés, sous forme de « Partial Upsert » (seules les colonnes transmises sont écrites)._action: "delete"supprime l’entrée d’un client,customers_prices_replace: truebascule en mode « miroir complet » ; le client est identifié viacustomers_idoucustomers_id_extern(numéro de client WaWi). - Importation des clients :
customers_id_externetcustomers_group_idsont désormais accessibles en écriture ;PUTpermet également d’adresser le client sans e-mail viacustomers_idoucustomers_id_extern(gestion des remises et des données de base uniquement).
v2.56.0
16 juillet 2026Extensions internes
- Aucune modification des points de terminaison documentés : cette version étend exclusivement une interface de support interne de XONIC. Les opérations d’exportation, d’importation et de suppression (DELETE) fonctionnent comme auparavant.
- Intégrations existantes : elles restent opérationnelles sans modification – le numéro de version est simplement mis à jour.
v2.55.0
15 juillet 2026Extensions internes
- Aucune modification des points de terminaison documentés : cette version étend exclusivement une interface de support interne de XONIC. Les fonctions d'exportation, d'importation et de suppression fonctionnent comme auparavant.
- Intégrations existantes : elles restent fonctionnelles sans modification – seul le numéro de version augmente.
v2.54.0
14 juillet 2026Commandes : les champs de date – notamment la date de prestation – peuvent désormais être définis pour chaque poste. Cela est nécessaire pour les factures groupées dans lesquelles chaque lot de travaux comporte sa propre date de prestation (les documents l’indiquent alors sous la ligne d’article correspondante plutôt qu’une seule fois dans l’en-tête du document). De plus, la fonction « PUT /orders » (Ajouter des lignes ) avec l’option « products_mode: "append" » (Ajouter des lignes de commande ) permet d’ajouter des lignes à une commande existante; les totaux sont ensuite recalculés. Les commandes qui sont déjà considérées comme des factures – parce qu’un numéro de facture leur a été attribué ou que la série de numéros individuelle est désactivée – sont refusées avec le message « ORDER_ALREADY_INVOICED » : une facture émise ne peut pas être modifiée a posteriori. Les mises à jour de statut, de suivi et de date ne sont pas affectées par cette mesure.
v2.53.0
14 juillet 2026Commandes : le groupe de dates de l’éditeur de commande peut désormais être défini via l’API – service_date (date de prestation), estimated_service_date, shipping_date, estimated_shipping_date, invoice_date (date de facturation), invoice_payment_term_date (délai de paiement) ainsi que la date souhaitée desired_delivery_date sous forme de texte libre. S'applique à la création d'une nouvelle entrée (POST) et à la mise à jour (PUT) ; les dates sont analysées avec une certaine tolérance.
v2.52.0
14 juillet 2026Importation de produits : grâce à « import_blocks », il est possible de protéger de manière ciblée certains champs d’un produit existant contre l’importateur XML – par exemple lorsque la description en allemand provient du système de gestion des stocks, mais que la description en anglais est gérée dans la boutique. Il s’agit de l’équivalent programmatique de l’onglet du backend « xoPort Interface de données (XML) ». Le nom et la description (par langue) ainsi que sept catégories de prix peuvent être protégés.
v2.51.0
11 juillet 2026Importation de produits : extra_fields accepte désormais les champs supplémentaires soit via l’ID du champ, soit via le nom du champ – sous forme d’objet ou de liste, y compris la structure fournie par l’exportation JSON (aller-retour export/import). Auparavant, seule la liste avec products_extra_fields_id était prise en compte ; les orthographes divergentes étaient rejetées sans avertissement. Les champs supplémentaires non identifiables génèrent désormais un avertissement « EXTRA_FIELD », et un champ qui se trouve par erreur au niveau supérieur au lieu d’être dans « extra_fields » est mentionné dans l’avertissement avec l’ID de champ correspondant. Cela concerne notamment les champs Google Shopping.
v2.50.0
30 juin 2026Optimisations internes et améliorations de la stabilité de l'API xoPort.
v2.49.0
25 juin 2026DELETE /customer_group/{id} (Portée customer_groups:delete) : suppression d'un groupe de clients avec deux mécanismes de protection stricts – le groupe 0 (« clients finaux ») ne peut pas être supprimé (403), et un groupe auquel des clients sont encore affectés est refusé (409, il faut d'abord regrouper les clients). Nettoie toutes les données associées (remises, offres spéciales, tarifs de groupe, entrées de filtrage).
v2.48.0
25 juin 2026Nouvelle entité customer_groups (exportation + importation) : énumérer et gérer les groupes de clients via l’API – y compris les restricted_categories_ids parsemées (liste noire des catégories du groupe). POST/PUT avec validation d’énumération et durcissement des ID ; POST nécessite une customers_group_id explicite (pas d’AUTO_INCREMENT). Deux nouvelles portées : customer_groups:read + customer_groups:write.
v2.47.0
25 juin 2026Liste noire des catégories et des groupes de clients : restricted_customer_groups désormais également disponible pour les catégories (auparavant uniquement pour les produits). L’importation synchronise customers_groups.restricted_categories, l’exportation renvoie ce champ. Récursif: si l’on bloque une catégorie parente, toutes les sous-catégories actives sont également bloquées.
v2.46.0
20 juin 2026Téléchargement de médias entity_type=static: nouveau mode « wildcard » / « liste noire ». Avec XOPORT_MEDIA_STATIC_FOLDERS = '*', tous les sous-dossiers de images/ sont accessibles en écriture, à l’exception de ceux gérés par le système de gestion des images (source/, thumbnail/). La liste d’autorisation stricte reste la valeur par défaut ; ce mode est optionnel. Renforcement supplémentaire : jeu de caractères strict pour les noms de dossiers, confinement des chemins d’accès sous images/ et protection contre l’écrasement (fichier existant uniquement avec overwrite:true). Nouveaux codes d’erreur PROTECTED_TARGET_FOLDER (403) et FILE_EXISTS (409).
v2.45.0
19 juin 2026Importation de produits storages[]: mise à jour partielle. Les stocks par entrepôt ne sont désormais enregistrés que pour les champs effectivement transmis (INSERT … ON DUPLICATE KEY UPDATE au lieu de REPLACE). Une charge utile partielle telle que {"storages_id":1,"products_reorder_level":50} ne modifie ainsi que le niveau de stock déclaré et ne remet plus à 0 les autres colonnes de stock. Les charges utiles complètes restent rétrocompatibles.
v2.44.0
18 juin 2026API Appointments : point de terminaison de calendrier autonome
- Nouvelle ressource de premier niveau
appointmentsavec CRUD complet :GET /appointments,POST/PUT /appointmentsainsi queDELETE /appointment/{id}(suppression temporaire → CalDAV-Tombstone). - Les rendez-vous sont créés via la logique centrale de gestion des rendez-vous (CalDAV-UID,
updated_at) et apparaissent immédiatement dans le calendrier des administrateurs responsables ainsi que dans la synchronisation CalDAV. - Champs, entre autres :
startdate(obligatoire),enddate/deadline,allday/vacation/private/done, rappels, titre/description/lieu (multilingue),responsibilities,followers,categoriesetrelationships(lien vers un ticket, une commande, un client ou un projet). - Filtres d’exportation : plage horaire, responsabilité, lien (par ex.
?ticket_id=) ainsi que?last_modified=pour la synchronisation delta.PUTcontient les champs non transmis. - Trois nouvelles portées :
appointments:read,appointments:write,appointments:delete.
v2.43.0
18 juin 2026API des tickets : création de rendez-vous associés
POST/PUT /ticketsaccepte désormais le champ facultatiflinked_appointments— pour chaque ticket, il est possible de créer directement des rendez-vous.- Chaque entrée génère un rendez-vous dans le calendrier et le lie au ticket. Responsables = les administrateurs affectés au ticket, Titre par défaut = objet du ticket.
- Équivalent du champ d’exportation existant «
linked_appointments» ; portée requise : «tickets:write».
v2.42.0
15 juin 2026Types d’entités de slider et slider d’actualités (à partir de Shop 4.8)
- À partir de XONIC 4.8 (toutes les versions postérieures à la version 4.7.15), la table
sliderutilise la paire de colonnes polymorphesentity_type(category/content/news) +entity_idau lieu decategories_id+content_id. - La charge utile du slider (exportation et importation) s'effectue désormais via
entity_type+entity_id. Les clients qui envoient encorecategories_id/content_iddoivent effectuer la mise à jour. - Nouveau type
news: les diapositives peuvent désormais également être associées à des articles d'actualité. Slider de la page d'accueil =entity_type=content,entity_id=0. - Les filtres d'exportation
?categories_id=/?content_id=sont conservés et sont mappés en interne vers le type d'entité. Les boutiques existantes sont migrées automatiquement via la fonction « Self-Heal ».
v2.41.0
14 juin 2026API multimédia : pièces jointes aux projets et aux tâches
POST /mediaAvecentity_type=project(outask), vous pouvez joindre directement des documents PDF à un projet xoCRM ou à une tâche.- Le fichier est enregistré dans l’espace de stockage interne et sécurisé du projet et apparaît immédiatement dans l’onglet « Fichiers » — idéal pour les documents internes tels que les plans de projet.
- Champs obligatoires :
entity_id(ID du projet ou de la tâche, vérifié),file_nameet une source (file_url,file_base64ou téléchargement multipart). - Actuellement, les fichiers PDF (
application/pdf) sont pris en charge ; portée requise :media:write.
v2.40.0
11 juin 2026API Projects : enregistrement d’un statut sans changement de statut
PUT /projectsou/project_tasksavecstatus_commentpermet désormais d’ajouter une entrée dans l’historique des statuts même sans changement de statut — idéal pour les comptes-rendus de réunion et les notes de travail.- Les entrées de tâches comportent l’
progress_percent— la barre de progression apparaît dans l’historique.
v2.39.2
11 juin 2026Correction d’un bug : frais d’options ponctuels dans l’interface utilisateur
- Lors de l’importation d’options avec présélection, l’
pre_optionest désormais également défini dans le masque d’options — auparavant, la ligne « plus » correspondant aux frais d’option uniques n’apparaissait pas sur la page du produit.pre_optionest également autorisé en tant que champ explicite dans la charge utile. - Correction au niveau du noyau : le prix de l’option était perdu lorsque le tableau des détails de l’option était entièrement vide.
v2.39.1
11 juin 2026Correction d’un bug : caches des produits après l’importation
- Après chaque importation de produits, les caches des produits sont mis à jour (présélection des options, étiquettes de prix) — comme lors d’une sauvegarde dans le backend.
- Auparavant, les majorations de prix liées aux caractéristiques et les modifications de prix définies via l’API n’étaient visibles dans le front-end qu’après une nouvelle sauvegarde manuelle.
v2.39.0
11 juin 2026Importation de produits : caractéristiques et options (options[])
- Les attributs de produit peuvent désormais être créés via
POST/PUT /Import/JSON/products: pour chaque entrée,option_idouoption_name+value_idouvalue_name— les options/valeurs manquantes sont créées automatiquement. - Champs de contrôle :
option_type(par ex. 5 = affichage uniquement),option_sort,option_required,price(supplément),pre_select,status,model,ean,quantity,weight,image. - Les combinaisons déjà attribuées sont ignorées (avertissement
OPTION_EXISTS_SKIPPED) ;options_replace: truereconstruit entièrement les attributs du produit.
v2.38.0
11 juin 2026Produits : liste de blocage des groupes de clients
- Nouveau champ «
restricted_customer_groups[]» dans l’exportation et l’importation de produits : identifiants des groupes pour lesquels le produit est bloqué. - L’importation remplace intégralement la liste de blocage si ce champ est inclus dans la charge utile ; un tableau vide supprime tous les blocages.
- Cela permet de transférer des restrictions de visibilité (par exemple, réservé à un groupe de clients spécifique) d’un produit à un autre via l’API.
v2.37.0
11 juin 2026Importation de produits : Click2Call et blocage de l'achat direct
- Deux nouveaux indicateurs de produit importables :
click2call(bouton d’appel à la place du panier) etnon_directcart(pas d’achat direct) — viaPOST/PUT /Import/JSON/products. - Comportement identique à
non_cart/non_price: seuls les champs définis sont modifiés.
v2.36.0
11 juin 2026API Projets : entrées de statut dans l'exportation
- Les projets et les tâches fournissent désormais
status_history[]avec — toutes les entrées de statut gérées dans le backend, y compris les commentaires (par exemple, les comptes-rendus de réunion). - Champs par entrée :
status_id+status_name,date_added,comments,progress_percent,user_id+user_name. - Simplement une mise à jour, pas de nouvelle version — il suffit d'installer
projects:readouproject_tasks:read.
v2.35.0
11 juin 2026API Projets : projets xoCRM et tâches de projet
- Deux nouveaux types d’entités :
projects(projets xoCRM) etproject_tasks(tâches de projet) — avec respectivement des fonctions d’exportation, d’importation et de suppression. - Points de terminaison :
GET /Export/JSON/projects(unique/plage/filtre,?include_tasks=1avec tâches intégrées en option),POST/PUT /Import/JSON/projects,DELETE /Delete/JSON/project/{id}— de même pourproject_tasks. - Six nouveaux champs d'application :
projects:read/write/delete+project_tasks:read/write/delete. - Projets : multilingues
descriptions[], catégories, attribution aux clients (customer_scope), chefs de projet (leader_admin_ids), liens vers les commandes/tickets (relationships[]),is_private. - Tâches : priorité (1-5), avancement (0-100 %), échéance, heures prévues/réelles, attribution aux responsables (
assigned_admin_ids). - Gestion des statuts : validation par rapport à la gestion des statuts, enregistrement automatique de l’historique des statuts lors de la création et des changements de statut (
status_comment,admin_id). - Suppression en cascade : la suppression d’un projet supprime également toutes les tâches associées ; les commandes/tickets liés sont simplement dissociés.
v2.34.0
10 juin 2026Importation de produits : automatisation des produits de deuxième choix et nouveaux champs
warranty_period: la durée de garantie est configurable ; une chaîne vide""remplace la valeur par défaut24m.products_xoport: le champ « marqueur » (par ex.googleblacklist) peut désormais être importé.images[]: Attribution d’images de produit supplémentaires par nom de fichier (remplace la galerie existante), y compris les textes alternatifs multilingues ; format tableau ou objet.storages[]: Définir les stocks par entrepôt (gestion multi-entrepôts) — uniquement si le système multi-entrepôts est activé ; le stock totalproducts_quantityreste distinct.downloads[]: Créer des téléchargements de produits (par ex. PDF) ;d_srcrenvoie vers un fichier situé dansfiles/.- Téléchargement de médias :
POST /mediaavecentity_type=downloadtélécharge des fichiers PDF/documents versfiles/.
v2.33.0
9 juin 2026Auteurs d'actualités : point de terminaison newsdesk_authors & author_id
- Nouveau point de terminaison
/newsdesk_authors: exporter les auteurs d’actualités en tant que ressource distincte (GET /newsdesk_authors,GET /newsdesk_author/{id}) et les créer (POST/PUT /newsdesk_authors). Portéenews:read/news:write. - Champs : neutres sur le plan linguistique
authors_name,authors_image,authors_email,authors_url,authors_company(remplacement du nom de l'entreprise pour les auteurs externes),authors_since_year,authors_status,sort_order; par langueauthors_jobtitleetauthors_bio. - Lien
author_id: la fonction d'importation/exportation d'actualités (newsdesks) inclut désormaisauthor_id— les articles peuvent être directement associés à un auteur.
v2.32.0
7 juin 2026Importation des commandes : parité de paiement pour la ligne fiscale et les informations d’adresse supplémentaires
- Ligne fiscale par taux :
ot_taxest désormais affiché pour chaque taux avec un libellé correspondant exactement au taux dans le format du frontend — « TVA 19 % en sus » en mode net ou « TVA 19 % incluse » en mode brut (uniquement siMODULE_ORDER_TOTAL_PREFIX=true) — à la place de l’ancienne ligne collective statique « TVA : ». Les montants restent inchangés. - Nouveau champ d’adresse
additional_address: désormais inclus dans les champs d’adresse autorisés — le complément d’adresse est repris aprèscustomers_additional_address,delivery_additional_addressetbilling_additional_address(plus d’avertissement «UNKNOWN_FIELD»).
v2.31.0
7 juin 2026Importation des commandes recalc: remises par catégorie et par client incluses dans le prix
- Le mode «
recalc» applique désormais au prix des lignes de commande non seulement les prix de groupe et les offres spéciales, mais aussi les remises par catégorie et par client (customers_discount+customers_groups_discount, y compris l’héritage des sous-catégories — même logique que sur l’interface publique). - Le prix normal fait toujours l’objet d’ une remise, tandis que l’ offre spéciale ne s’applique qu’en cas de «
d_special=1»; c’est le moins cher des deux prix effectifs qui prévaut. Ainsi, la commande transférée affiche exactement le prix que le client paie lors du paiement. - Effort maximal : en cas de problème, l’avertissement «
CATEGORY_DISCOUNT_UNAVAILABLE» s’affiche et le calcul s’effectue sans remise. Hypothèse : un client par requête. Les commandes d’invités/de la place de marché (sans «customers_id») restent inchangées.
v2.30.0
7 juin 2026Importation des commandes : parité dropshipping lors du paiement
- Caractéristiques « affichage uniquement » :
apply_default_attributesprend désormais également en charge les caractéristiques d’affichage avec présélection (type d’option 5, par exemple « Modèle »/« Indice de protection »), y compris le supplément signé — exactement comme elles apparaissent lors du paiement. Seules les caractéristiques internes masquées (type 6) restent exclues. - Prix d’achat et GTIN : en mode «
recalc», le prix d’achat (products_ek_priceissu deproducts_cost) et le GTIN/EAN (products_ean) sont ajoutés à la ligne de commande, à condition que l’appelant ne fournisse aucune information. - Nouvel indicateur
compute_shipping(niveau supérieur, valeur par défautfalse) : en l’absence d’unetotals.shippingexplicite, le mode de livraison le moins cher est calculé « en mode headless » via la pile de gestion des livraisons du front-end (shipping::cheapest()) pour l’adresse de livraison, puis enregistré sous la formeot_shipping(taux d’imposition = taux d’imposition dominant du produit). Best-effort : les erreurs ne génèrent pas d’exception, mais renvoient l’avertissementSHIPPING_AUTO_FAILEDouSHIPPING_AUTO_EMPTY— la commande est conservée. - Cas d’utilisation : transfert en dropshipping (par ex. SPV → SST), dans lequel la commande suivante doit comporter des caractéristiques, des codes EK/GTIN et des frais de port exactement identiques à ceux d’une commande manuelle passée sur la boutique.
v2.29.0
7 juin 2026Importation des commandes : envoi facultatif de la confirmation de commande
- Nouvel indicateur «
send_confirmation_email» (niveau supérieur,true) : une fois la commande créée avec succès, la confirmation de commande standard est envoyée au client — exactement comme lors d’un paiement normal ou via les importateurs de marketplace, y compris les destinataires en copie issus deSEND_EXTRA_ORDER_EMAILS_TO. - Destinataires et langue : e-mail issu de la commande créée (avec validation), langue issue de la charge utile ou de la commande.
- Retour d’information : le résultat est indiqué sous la forme «
confirmation_email_sent» (vrai/faux) dans l’enregistrement correspondant de la réponse. Les erreurs d’e-mail n’interrompent pas l’importation. - Valeur par défaut inchangée : sans ce drapeau, aucun e-mail n’est envoyé (entièrement rétrocompatible).
v2.28.0
7 juin 2026Importation des commandes : remplissage automatique des données client, résolution des SKU et attributs par défaut automatiques
- Adresse de facturation à partir du numéro de client : en cas de «
customers_id > 0» et d’«billing» incomplet ou manquant, l’adresse de facturation par défaut du client (fiche client + carnet d’adresses) est reprise — les champs explicitement fournis prévalent. «delivery» reste indépendant pour les adresses de livraison différentes. - Résolution des SKU : les articles peuvent être fournis uniquement via
products_model(= SKU) +products_quantity;products_idetproducts_namesont complétés à partir de la boutique. SKU inconnu → avertissementPRODUCT_MODEL_NOT_FOUND. - Attributs par défaut automatiques :
apply_default_attributes: truereprend dans la commande, pour chaque article ne disposant pas d’attributs propres, les valeurs d’options présélectionnées dans la boutique, y compris le supplément. - Correction du calcul des quantités : en mode «
recalc», le prix unitaire net est désormais enregistré correctement (auparavant, il était doublé dans le sous-total lorsque la quantité était supérieure à 1).
v2.27.1
2 juin 2026Tickets : réponse publique via l’API identique à celle de l’outil de gestion
- Profil de l’auteur : dans «
is_public_reply=true», l’entrée d’historique apparaît sous le profil du ticket de l’administrateur intervenant (source :admin.ticket_settings) au lieu d’apparaître sous le prénom et le nom d’utilisateur. Ordre : facultatifticket_admin_id→admin.ticket_settings→TICKET_DEFAULT_ADMIN_ID→ nom d’utilisateur. - « Réponse intégrée » : l’indicateur
ticket_customer_notified_embeddedest activé en cas de réponse publique avec envoi d’e-mail — le texte de la réponse est intégré à l’e-mail du client. - CC/BCC : les destinataires CC/BCC du ticket sont enregistrés dans l’historique (badge visible) et inclus dans l’e-mail.
- Vérification de l’envoi d’e-mail : la valeur renvoyée par l’envoi d’e-mail est analysée — un échec d’envoi génère désormais une erreur au lieu d’un retour silencieux
success.
v2.26.0
1er juin 2026Exportation des commandes : pagination au niveau SQL (correction de mémoire)
- Problème : jusqu’à présent,
GET /Export/JSON/orderschargeait l’intégralité de l’enregistrement de commande (y compris les lignes, les totaux et le suivi) en mémoire, puis ne le découpait qu’ensuite via?limit/?offset— sur les boutiques enregistrant un grand nombre de commandes, cela entraînait une erreur fatale PHP « Allowed memory size exhausted », même avec?limit=1. - Solution :
LIMIT/OFFSETsont désormais — à l’instar du point de terminaison/products— directement appliqués à la requêteorders_id. Seule la page demandée est chargée (par défaut 50, max. 250 viaXOPORT_API_MAX_LIMIT). - Compatible avec les filtres :
stats.totalrespecte les filtres actifs (?status,?customer_id,?date_from/to,?since,?products_id, …) ; la réponse contientstats.total/limit/offset/has_more. - Inchangé : la ressource unique
/order/{id}et la plage/orders/{a}:{b}restent délibérément sans pagination (comme pour les produits).
v2.25.0
30 mai 2026Tickets : signature de l’administrateur sur les réponses publiques
- Signature automatique : pour
is_public_reply: true, la requête PUT/Import/JSON/ticketsajoute désormais automatiquement au texte de la réponse la signature de l’administrateur enregistrée dans le backend (admin_settings.signatures.tickets), tant dans l’historique que dans l’e-mail envoyé au client, exactement comme l’outil de réponse du backend. - Langue : langue par défaut de la boutique ; si celle-ci n’est pas disponible, le système utilise la première signature enregistrée. Si l’administrateur n’a pas de signature, le texte reste inchangé.
- Désactivation : le drapeau optionnel
append_signature: false(strictement booléen) désactive l’ajout de la signature. - Important pour les clients : ne plus envoyer de signature propre dans «
ticket_comments» — sinon, elle apparaîtra en double.
v2.24.0
29 mai 2026Tickets : réponses publiques + notification client
- Nouveauté dans le bloc de commentaires de la requête PUT
/Import/JSON/tickets: deux indicateurs booléens facultatifs par élément —is_public_reply(true → l’entrée dans l’historique devient publique) etnotify_customer(true → e-mail envoyé au client). Les deux ne sont effectifs qu’en mode strict=== true; toutes les autres valeurs sont ignorées. - Comportement par défaut inchangé : sans indicateurs, le commentaire reste interne (
ticket_internal_comment=1, pas d’e-mail) — rétrocompatible avec tous les clients v2.11.0+. - L’envoi d’e-mails utilise le même modèle
$mail_ticket_update_with_contentque l’outil backend (xpanel/tools-ticket-show.php), y compris les champs CC/BCC issus deticket_additional_data.receiverset les pièces jointes de la ligne d’historique correspondante. - Paramètre de sécurité par défaut :
is_public_reply=truesansadmin_id > 0valide revient automatiquement à « interne » + « sans e-mail » et renvoie unerror. Aucune nouvelle portée n’est nécessaire (tickets:writesuffit). - Cas d’utilisation : les agents IA ou les outils externes peuvent désormais répondre aux tickets non seulement sous forme de note interne, mais aussi en tant que véritable réponse au client — avec un indicateur d’opt-in clair, afin qu’une « publication accidentelle » soit pratiquement impossible.
v2.23.0
29 mai 2026Correction relative à la ressource unique + cohérence de l’API
- Correction de bug :
GET /products/{id}renvoie désormais exactement un produit. Auparavant, en raison du routage des chemins au pluriel, la sémantique de plageWHERE products_id >= {id}s’appliquait — le client voyait, via.data[0], un produit aléatoire issu du résultat de l’analyse. - CHANGEMENT MAJEUR pour les catégories : le format de requête
?id=introduit dans la v2.1.0 pour/categories?id={id}a été supprimé. La ressource unique n’est désormais disponible dans toute l’API que sous forme de chemin d’accès (/categories/{id},/products/{id}). Justification : une URL canonique par ressource, pas de chevauchement avec les filtres en masse (?limit/?offset/?status/?language). - Inchangé : la forme « range »
/products/100:200et la pagination en masse (?limit=&offset=). - Remarque (latente) : le même comportement de routage des chemins au pluriel existe structurellement sur
suppliers/manufacturers/vouchers/customers/orders/newsdesks/cms/sliders— ticket distinct prévu.
v2.22.0
26 mai 2026API Slider : les diapositives promotionnelles constituent un nouveau type d’entité
- Nouveaux points de terminaison :
GET /slider(s),POST/PUT /slider,DELETE /slider/{ID}. - Trois nouvelles portées :
slider:read,slider:write,slider:delete(ID 56 à 58). - Filtres :
status,type,categories_id,content_id,language. -
languages{}imbriqués avectitle,description,direction,width,image,image_mobile,video,video_mobile. - Contexte : jusqu’à présent, les diapositives promotionnelles ne pouvaient être mises à jour que via le backend. Le nouveau point de terminaison permet, par exemple, de corriger a posteriori des liens de diapositives erronés via
PUT /slider.
v2.21.0
19 mai 2026Importation des commandes : modes « Totals », taxe automatique et contrôle de dérive
- Dérivation automatique à partir de
customers_group_id— Charge utile en cascade → Fiche client → 0 (invité). - Déduction automatique depuis
tax_flagà partir decustomers_groups.show_tax+customers_groups.tax_exempt(0 = net, 1 = brut, 2 = exonéré d’impôt). Les valeurs explicites de la charge utile ont la priorité. - Trois modes de calcul des totaux (
totals_mode) :auto(par défaut, se fier aux prix fournis par l’appelant),recalc(rechargerproducts_price+products_taxdepuis la base de données, prise en compte du groupe de clients et du pays — idéal pour les importations depuis une place de marché avec uniquement le SKU et la quantité),verbatim(totals.totalest conservé à l’identique, idéal pour les remboursements et les réimportations historiques). - Contrôle de dérive de bout en bout via
expected_total+strict_totals. En cas d’écart > 0,01 € : par défaut = avertissement, avecstrict_totals: true= interruption atomique viaOrderBuilderException('TOTAL_DRIFT', 422)avant la première insertion des totaux. - Validation par liste blanche pour toutes les entités « Orders » (
orders,order_address,order_product,order_totals,order_external_reference) — les clés inconnues génèrent un avertissement de déduplication «UNKNOWN_FIELD», comme pour les produits/clients. - Suite PHPUnit: 17 tests, 33 assertions (
core/lib/classes/Tests/Order/OrderBuilderTest.php).
v2.20.0
19 mai 2026Point de terminaison « Commandes » et webhook générique
- Nouveau point de terminaison
POST/PUT /Import/JSON/ordersavec la portéeorders:write— créer et mettre à jour des commandes via l’API. - Service générique
\\Xonic\\Order\\OrderBuilder(core/lib/classes/Order/OrderBuilder.php) — réutilisable pour les importateurs Marketplace et WaWi. - Exceptions typées via
\\Xonic\\Order\\OrderBuilderExceptionavecerrorCode,httpCodeetdetails. - Calcul de la taxe : prend en charge le mode brut (
tax_flag=1) et le mode net (tax_flag=0). - Enregistrement des stocks via
xo_stock_change(best-effort : les échecs sont renvoyés sous la formewarnings). - Suivi des références externes : enregistrement automatique dans
TABLE_ORDERS_EXTERNAL_REFERENCESen cas d’ID externe. - Réaction marketing
send_webhook— webhook sortant générique avec signature HMAC-SHA256 et charge utile enrichie (produit, commande, client, ticket).
v2.19.0
15 mai 2026Point de terminaison média : téléchargements d’actifs statiques (entity_type=static)
- Nouveau mode
entity_type=staticdans le point de terminaison multimédia — permet le téléchargement de ressources de marque (logos, images d’interface) sans liaison à la base de données. - Configuration de la liste blanche: dossiers de destination autorisés via
XOPORT_MEDIA_STATIC_FOLDERS(par défaut :schnittstellen,marketplaces) — empêche les attaques par traversée de chemin. - Champs obligatoires:
entity_type,target_folder,file_nameainsi qu’une source (file_url,file_base64ou téléchargement multipart). - Comportement par défaut: écrase les fichiers existants (
overwrite=true). La réponse contient le chemin d'accès direct à l'image. - Restrictions: pas d’enregistrement dans la base de données, pas de vignettes, pas de DELETE, pas de titres multilingues. Une requête PUT avec
staticest rejetée avec le code d’erreurSTATIC_UPDATE_NOT_SUPPORTED. - Cas d'utilisation: gestion via l'API des logos de la place de marché, de l'habillage de l'interface et des ressources statiques du front-end.
v2.18.0
12 mai 2026Import/export de produits : ventes incitatives (ajouts au panier)
- Nouveau champ «
upsells» dans le point de terminaison « Products » — similaire à «xsells», mais pour les suggestions « À associer » dans le panier (tableauproducts_upsell). - Export: pour chaque produit, un tableau contenant
products_model,products_id(source) etsort_order. L'exportation d'un seul produit fournit les ventes incitatives du produit demandé (filtre sur le PID source). - Importation via PUT: accepte un simple tableau de chaînes de caractères représentant des modèles (
["MODEL-A", "MODEL-B"]) ou un tableau d’objets ([{"products_model": "MODEL-A", "sort_order": 0}]). - Sémantique de remplacement: les ventes incitatives existantes sont entièrement supprimées avant l’insertion (DELETE puis INSERT). Les références à elles-mêmes et les modèles inconnus sont ignorés sans avertissement.
- Cas d’utilisation: remplissage des suggestions de produits complémentaires dans le panier via l’API — configurable individuellement pour chaque produit (pas de liste globale par défaut).
v2.17.0
7 mai 2026Importation de produits : extension des offres spéciales
- Bloc « Offres spéciales » complet :
specials[]par produit aveccustomers_group_id, prix spécial direct oudiscount_percent. - Période et statut :
specials_begin,specials_end(aliasexpires_date) ainsi questatus/special_status. - Dénominations des offres :
specials_price_idouspecials_price_name(en fonction de la langue) avec mise à jour automatique deslp. - Mise à jour et suppression : « upsert » via
(products_id, customers_group_id), suppression viaaction: deleteoudelete: 1. L'ancien blocspecialreste rétrocompatible.
v2.16.0
29 avril 2026API Media – Point de terminaison /media entièrement implémenté
- Prise en charge CRUD complète : exportation (GET), importation (POST/PUT) et suppression (DELETE) pour la bibliothèque d’images de produits (
products_images) — jusqu’à présent, toutes les opérations étaient des stubs501 Not Implemented. - Trois modes de téléchargement :
file_url(téléchargement depuis le serveur via cURL),file_base64(en ligne) etmultipart/form-data(filede champ). Choix en fonction du client et de la taille du fichier. - Validation : détection MIME (
image/jpeg|png|gif|webp), limite de taille de fichier viaXOPORT_MEDIA_MAX_FILESIZE(par défaut 10 Mo), prévention automatique des conflits, nettoyage des noms de fichiers. - Titres multilingues :
descriptions[]aveclanguage_idoulanguage_codepar image. La requête PUT avecdescriptionsremplace l’intégralité (sémantique de synchronisation complète). - Promotion de l’image principale : l’utilisation facultative de
is_main=1lors d’un POST définit en plusproducts.products_image. - Vignettes à la demande : les URL pour mini/small/medium/large/xlarge sont renvoyées dans chaque réponse — la génération physique s'effectue à la volée via
image_thumb.phplors du premier appel. - Suppression sécurisée (DELETE) : supprime l’enregistrement, les lignes de description, le fichier source et toutes les vignettes — mais uniquement s’il n’existe plus aucune autre référence de la base de données pointant vers ce nom de fichier. Suppression en masse via
?entity_id=ou{ids:[…]}. - Nouvelles portées :
media:read,media:write,media:delete.
v2.15.0
23 avril 2026Importation de produits : champs « Famille/Variantes » + correction automatique des conflits SEO
- Champs « Famille/Variantes » lors de l’importation :
products_family(balise de chaîne),products_family_type(entier,3= maître-esclave des variantes) etproducts_master(entier, PID du maître ou auto-référence) sont désormais acceptés — ce qui permet les regroupements maître-esclave (par exemple, variantes de packs) via l’importation JSON - Workflow maître-esclave : créer le maître → lire le PID à partir de
records[0].products_id→ effectuer un deuxième PUT avecproducts_master = eigene PIDpour l’autoréférence, puis attribuer les esclaves - Contrôle d’unicité SEO : lors de l’importation,
seo_name(ou, à défaut,products_name_as_seo) est comparé à tous les autres produits — de la même manière que dans la logique du backend - Correction automatique : en cas de conflit de slug, le nom est automatiquement corrigé en
<slug>-<PID>(viatep_search_new_seo()) — l’importation se poursuitsuccess: true - Avertissements de réponse : les corrections sont signalées dans
warnings[]avectype: "SEO_NAME_CORRECTED", y comprisrequested,correctedetconflicting_with.{products_id, products_model, products_name} - Couvre une faille existante : le backend signaledésormais les conflits de slugs, alors que l’API les ignorait jusqu’à présent et générait des produits introuvables
v2.14.0
22 avril 2026Importation de produits : alias courts pour les champs méta-SEO
- Nouveaux alias courts :
title_tag,desc_tag,keywords_tagsont désormais acceptés dans l’importation de produits — en cohérence avec l’API des catégories - Mappage interne : les alias sont mappés aux colonnes de la base de données
products_head_title_tag,products_head_desc_tagetproducts_head_keywords_tag - Priorité : les noms complets des colonnes ont la priorité lorsque les deux variantes sont envoyées
- Rétrocompatibilité : les charges utiles existantes contenant les noms de champs longs fonctionnent sans modification
- Exportation : continue de fournir les champs
products_head_*_tag(et non les alias)
v2.13.0
20 avril 2026Historique SEO : redirections automatiques pour tous les types d’entités
- En cas de changement de nom via une importation JSON (PUT), des entrées «
seo_history» sont désormais créées automatiquement pour les produits (p), les catégories (c), les fabricants (m), les actualités (n) et le CMS (s) — les anciennes URL sont redirigées vers les nouvelles via une redirection 301 - Produits : correction — fonctionne désormais également en cas de changement de nom SANS
seo_nameexplicite (via la régénération automatiqueproducts_name_as_seo) - Fabricants : indépendant de la langue (une entrée
sh_history, une ligne de description par langue avec le même slug) - Actualités et CMS : spécifiques à chaque langue (comme les catégories/produits)
- Idempotent : une même charge de renommage ne génère pas de deuxième entrée
- Aides «
persistSeoHistory()» + «buildSeoHistoryDeletestamp()» extraites de «ImportJSON» (DRY)
v2.12.0
20 avril 2026Liste des produits par catégorie (point de terminaison allégé)
- Nouveau sous-point de terminaison :
GET /categories/productlist— Mappage allégé des catégories vers les identifiants de produits et les modèles - Paramètres de requête :
?categories_id=,?status=,?include_inactive_products=,?language= - Réponse : par catégorie, un tableau contenant
categories_id,categories_name,products_countetproducts[], ainsi queid+model - Économie de mémoire : une seule requête SQL au lieu de plus de 12 relations
Pagination au niveau SQL pour les produits
- Correction :
GET /productsutilise désormais la pagination au niveau SQL (LIMIT/OFFSET directement dans la requête) - Avant : tous les produits + relations chargés en mémoire, puis
array_slice() - Après : seule la page demandée est chargée depuis la base de données — plus aucune limite de mémoire
- Récupération individuelle via
/products/{id}et les plages reste inchangée
v2.11.0
13 avril 2026
- Tickets CRUD complet : points de terminaison d’importation (POST/PUT) et de suppression pour les tickets. Les portées «
tickets:write» et «tickets:delete» sont désormais actives. - Export :
linked_appointments[]: les rendez-vous CRM associés sont désormais inclus dans l’export pour chaque ticket (ID du rendez-vous, heure de début/fin, titre, description, lieu). - Import POST (Créer) : champs obligatoires
ticket_subject,ticket_customers_email,ticket_customers_name. Génèreticket_link_id, crée le répertoire de téléchargement, commentaire initial facultatif + attributions d’administrateur. - Importation PUT (Mise à jour) : modification du statut/de la priorité/du service, ajout de commentaires internes (
ticket_internal_comment=1toujours).admin_idest un champ obligatoire pour les commentaires (0 = système). - Suppression : suppression en cascade (status_history → admins → followers → appointments_relationships → CRM followers → fichiers → ticket).
- Portées :
tickets:write(importation/mise à jour),tickets:delete(suppression) – auparavant marquées comme « prévues », désormais pleinement opérationnelles.
v2.10.0
9 avril 2026
- Pagination globale : tous les points de terminaison d’exportation prennent en charge
?limit=n&offset=n. Limite par défaut : 50, limite maximale : 250 (configurable viaXOPORT_API_MAX_LIMIT/XOPORT_API_DEFAULT_LIMIT). La réponse contientstats.count,stats.limit,stats.offset,stats.has_more. - Tickets – Nouveaux filtres :
?admin_id=npour les tickets attribués (INNER JOIN sur ticket_to_admins) et?created_by_admin_id=npour le filtre par créateur. - Protection de la mémoire : la pagination automatique pour les grands ensembles de données empêche l'épuisement de la mémoire.
v2.9.0
8 avril 2026
- API des tickets (exportation) : nouveaux points de terminaison
GET /ticketsetGET /ticket/{id}pour l’exportation des tickets avec l’historique complet des conversations, les administrateurs assignés et les abonnés. - Points de terminaison pour les pièces jointes :
GET /ticket_attachments/{id}pour la liste des métadonnées (nom, taille, type MIME) etGET /ticket_attachment/{id}?file=namepour le téléchargement binaire avec protection contre le parcours de chemin. - Filtres de requête :
?status=,?priority=,?department=,?customer_id=,?type=,?date_from=&date_to=,?last_modified=,?language= - Nouveaux scopes :
tickets:read(implémenté),tickets:write,tickets:delete(implémenté dans la version 2.11.0) - Métadonnées :
ticket_statuses,ticket_priorities,ticket_departmentsdans chaque réponse
v2.8.1
11 mars 2026
- Correction de bug : Catégories
last_modified: désormais toujours définies lors des mises à jour PUT — même si seules les donnéeslanguages(description, nom, etc.) sont mises à jour. Auparavant,last_modifiedn’était mis à jour que si des champs de la table principale (status, parent_id, etc.) étaient également envoyés. - Newsletters
ALLOWED_FIELDS:languagesajouté à la liste des champs autorisés — plus d’avertissement «UNKNOWN_FIELD» lors de l’importation de newsletters multilingues.
v2.8.0
6 mars 2026
- API des abonnés aux newsletters : nouveaux points de terminaison pour les abonnés aux newsletters (exportation/importation/suppression) avec prise en charge des DOI.
- API des campagnes de newsletter : nouveaux points de terminaison pour les campagnes de newsletter (exportation/importation/suppression) avec format multilingue.
- Nouveaux scopes :
newsletter:read,newsletter:write,newsletter:delete,newsletters:read,newsletters:write,newsletters:delete - Prise en charge des DOI :
SHOP_NEWSLETTER_DOUBLE_OPT_INLa configuration est respectée, e-mail de confirmation lorsque le DOI est activé. - Synchronisation avec les fournisseurs : synchronisation automatique avec des fournisseurs externes (Cleverreach, Mailchimp, Optimizely) via
xoNewsletter. - Conformité au RGPD : journalisation de la confidentialité lors de l'importation/la suppression, suppressions en cascade documentées.
- Contrôles de sécurité : campagnes verrouillées protégées (
409 LOCKED), newsletters envoyées non supprimables (409 HAS_SENT_ENTRIES). - Filtres d'abonnés :
?status=confirmed|unconfirmed,?email=,?customer_id=,?language_id=,?last_modified= - Filtre par campagne :
?status=,?language_id= - Suppression en masse : possibilité de supprimer plusieurs abonnés via le corps JSON (par ID ou par e-mail)
v2.7.0
25 février 2026
- API Contracts : nouveaux points de terminaison pour les contrats/abonnements (exportation/importation/suppression).
- Point de terminaison « Status » : point de terminaison dédié
PUT /contracts/{id}/statuspour les changements de statut. - Nouveaux champs d'application :
contracts:read,contracts:write,contracts:delete,contracts:write - Filtres de requête :
?status=,?customer_id=,?product_id=,?interval=,?date_from=&date_to=,?active=1 - Données imbriquées : attributs, domaines, historique des statuts, commandes
- Suppression en cascade : attributs → domaines → liens de commande → historique des statuts → contrat
v2.6.0
24 février 2026
- API d'historique SEO : nouveaux points de terminaison pour les redirections SEO (exportation/importation/suppression).
- Redirection automatique : en cas de modification du « seo_name » lors de l’importation JSON d’un produit ou d’une catégorie, des entrées d’historique SEO sont automatiquement créées (de la même manière que pour l’importation XML).
- Nouveaux champs d’application :
seohistory:read,seohistory:write,seohistory:delete - Filtres de requête :
?type=,?base_id=,?language=,?expired=1 - Suppression en masse : suppression via le corps JSON ou un filtre de requête
v2.5.0
23 février 2026
- Champs produit étendus : 19 nouveaux champs pour les données contractuelles et logistiques dans l'importation de produits.
- Champs contractuels :
contract,contract_use_current_price,contract_option— Les produits contractuels peuvent désormais être entièrement créés via l’API. - Champs logistiques :
products_cost,products_inventory_management,products_min_qty,products_max_qty,products_qty_blocks,products_base_price - Champs « Article » :
products_sort_order,products_ean,products_free_shipping,products_image - Indicateurs :
service,sitemap,non_cart,non_price - Mappages :
shipping_profile,products_unit_id,base_unit_id
v2.4.2
19 février 2026
- Importation de produits : format «
languages» imbriqué : cohérent avec l'exportation et toutes les autres entités (catégories, rédactions, CMS). Accepte les{"languages": {"de": {...}, "en": {...}}}avec des codes ISO ou des identifiants numériques. - Remplissage automatique lors de l'insertion (INSERT) : les langues manquantes sont automatiquement renseignées à partir des données de la langue principale.
- Suppression du format plat :
products_name+language_idau niveau supérieur n’est plus pris en charge. - Aller-retour symétrique : Export → Import → Export donne des données identiques.
v2.4.1
19 février 2026
- Champs SEO dans l’importation de produits : 7 nouveaux champs :
products_head_title_tag,products_head_desc_tag,products_head_keywords_tag,seo_name,products_url,products_checkout_description,products_image_title - Permet un aller-retour complet d'exportation→importation pour tous les champs de description des produits.
v2.4.0
6 février 2026
- Point de terminaison CMS : nouveau type d'entité
cmsavec opérations CRUD complètes (exportation/importation/suppression). - Nouvelles portées :
cms:read,cms:write,cms:delete - Contrôles de sécurité : pages système (ID 1 à 999) protégées,
content_lockrespecté - Paramètres de requête :
?status=,?module=,?language= - Prise en charge multilingue avec le format
languagesimbriqué
v2.3.0
31 janvier 2026
- CRUD fournisseurs : nouveaux points de terminaison pour les fournisseurs (exportation/importation/suppression)
- Extension de l'exportation de produits : champs
videos,suppliers,contenteditor - Importation de produits étendue :
categories_ids,groups,specials,extra_fields,badges,xsells,tabs,videos,suppliers,contenteditor - Importation des fabricants : tous les champs GPSR (coordonnées UE + hors UE)
- Nouveaux domaines d'application :
suppliers:read/write/delete - Stubs : marketing, newsletter, points de contact médias (501 pas encore implémenté)
v2.2.0
27 janvier 2026
- Avertissements relatifs aux champs inconnus : la réponse contient désormais un tableau «
warnings» pour les champs inconnus/ignorés - Déduplication : chaque champ inconnu n'apparaît qu'une seule fois, même en cas d'importation en masse de plus de 100 enregistrements
- Champs imbriqués : vérifie également les objets `
languages.*` et `addresses[]` - Non bloquant : la requête est traitée avec succès malgré les avertissements (loi de Postel)
- Objet « Warning » :
{type, field, entity, message, first_occurrence}
v2.1.0
27 janvier 2026
- Séparation des méthodes HTTP RESTful :
POST= uniquement INSERT (création de nouveaux enregistrements)PUT= uniquement UPDATE (mise à jour d'enregistrements existants)
- Validation stricte : POST avec un ID existant → 409 Conflict, PUT avec un ID inconnu → 404 Not Found
- Nouveau champ de réponse : tableau «
records» contenant «{index, entity_id, status}» pour chaque enregistrement - Code HTTP 405 « Method Not Allowed » en cas de méthode incorrecte (par ex. DELETE sur le point de terminaison d’exportation)
- Les 8 points de terminaison d’entité prennent en charge POST/PUT : categories, products, customers, manufacturers, newsdesks, newsdeskcats, faq, faqcats
v2.0.3
26 janvier 2026
- Points de terminaison DELETE pour newsdesks et newsdeskcats
- Contrôles de sécurité : les catégories comportant des sous-catégories ou des articles associés ne peuvent pas être supprimées
- Codes d'erreur :
HAS_SUBCATEGORIES,HAS_NEWS - Vidéage du cache après une commande DELETE
v2.0.2
26 janvier 2026
- Newsdesk
categories_idslors de l'exportation et de l'importation - Les articles d'actualité se voient attribuer des catégories (comme les produits)
- Vidéos de cache après l'importation de newsdesks/newsdeskcats
- Importation de « newsdesks/newsdeskcats » au format «
languages» imbriqué
v2.0.1
26 janvier 2026
- Importation des catégories au format «
languages» imbriqué - Clés de langue utilisables sous forme de code (
de,en) ou d'ID - Interface d'administration des clients OAuth2 avec recherche en temps réel et tri
- Journalisation de la charge utile avec le corps de la requête/réponse
v2.0.0 Changements majeurs
26 janvier 2026
- CHANGEMENT MAJEUR : identifiants des clients OAuth2 (RFC 6749)
- Suppression des clés API – migration vers OAuth2 requise
- Nouveaux points de terminaison :
POST /oauth/token,GET /me - Nouvelles tables :
xoport_oauth_clients,xoport_oauth_tokens - Préfixe de jeton :
xoat_, Préfixe d'ID client :xoc_ - Backend : Outils → Clients OAuth2 xoPort
v1.5.0
26 janvier 2026
- Points de terminaison FAQ (faq/faqcategories Export/Import/Delete)
/mePoint de terminaison pour l'introspection de la portée
v1.4.x
23 janvier 2026
- Points de terminaison DELETE pour les catégories, les produits, les fabricants et les clients
- Contrôles de sécurité contre la suppression accidentelle
- Correction d'un bug : double échappement dans les attributs HTML corrigé
v1.0.0 - v1.3.x
23 janvier 2026
- API JSON initiale avec exportation/importation
- Gestion multi-adresses pour les clients
- Importation de catégories avec auto-seo_name
- Filtre par langue, codes pays ISO-2
- Authentification par clé API (obsolète dans la v2.0)
Restez toujours à jour
En cas de changements majeurs, nous vous en informons via la newsletter.