Utilisation
Cette page vous emmène de la création du client jusqu'à l'écriture de données, en passant par la lecture et la gestion des erreurs. Tous les exemples sont en ESM (import) : le SDK @shopimind/sdk-js est ESM uniquement et requiert Node.js 18+.
Créer un client
Le point d'entrée est SpmClient.getClient(apiVersion, apiKey). Il renvoie une instance HTTP prête à l'emploi, authentifiée par la clé API de la boutique (en-tête spm-api-key).
import { SpmClient, SpmCustomers } from '@shopimind/sdk-js';
// Client pour l'API v1, authentifié par la clé API de la boutique (en-tête spm-api-key)
const client = SpmClient.getClient('v1', process.env.SHOPIMIND_API_KEY!);L'URL de base par défaut est https://core.shopimind.com/v1. La version ('v1') est ajoutée automatiquement à la fin de l'URL de base.
Toutes les options
Le troisième argument est un objet SpmClientOptions — toutes les clés sont facultatives.
const client = SpmClient.getClient('v1', 'votre-cle-api', {
baseUrl: 'https://core-staging.shopimind.com',
headers: { 'x-trace-id': 'abc-123' },
timeout: 60000,
labelSource: 'web',
retry: { maxRetries: 3 },
});| Option | Type | Défaut | Rôle |
|---|---|---|---|
baseUrl | string | https://core.shopimind.com | URL de base de l'API |
headers | Record<string, string> | {} | En-têtes additionnels |
timeout | number | 30000 | Délai d'expiration de requête (ms) |
labelSource | string | null | 'web' | Injecté en label_source sur les POST/PUT de synchro. null désactive. |
retry | SpmRetryOptions | false | voir Résilience | Politique de réessais |
La base URL peut aussi venir de la variable d'environnement SHOPIMIND_CORE_API_BASE. Priorité : options.baseUrl > SHOPIMIND_CORE_API_BASE > défaut. Les barres obliques finales de la base sont supprimées avant d'ajouter le segment de version.
L'en-tête d'authentification
La clé API est toujours envoyée dans l'en-tête spm-api-key (en minuscules). Le SDK n'utilise aucune variante X-…. Voir Périmètre & versions pour le périmètre de la clé.
labelSource — d'où viennent vos données
Quand labelSource n'est pas null, le SDK injecte label_source: <valeur> dans le corps des requêtes POST et PUT (sur un objet, ou sur chaque élément d'un tableau). Cela permet à ShopiMind de savoir d'où proviennent les données synchronisées.
label_source n'est ajouté qu'aux écritures (POST/PUT) des entités que vous synchronisez dans ShopiMind :
- Clients :
SpmCustomers,SpmCustomersAddresses,SpmCustomersGroups - Produits :
SpmProducts,SpmProductsCategories,SpmProductsImages,SpmProductsManufacturers,SpmProductsVariations - Commandes :
SpmOrders,SpmOrdersCarriers,SpmOrdersStatuses - Bons de réduction :
SpmVouchers - Abonnés newsletter :
SpmNewsletterSubscribers
Les ressources de configuration et de lecture ne le reçoivent jamais (sources de données, custom data, événements, listes, contacts, paniers, connexion boutique, statistiques). Passez labelSource: null pour le désactiver entièrement.
L'enveloppe de réponse
Toutes les méthodes retournent le même objet, en succès comme en échec. Le SDK ne lève jamais d'exception sur une erreur HTTP : les codes 4xx/5xx et les erreurs réseau sont encodés dans l'enveloppe.
{
ok: true | false, // true si HTTP 2xx
statusCode: 200 | 4xx | 5xx | 0, // 0 en cas d'échec réseau (pas de réponse HTTP)
data: {/* corps renvoyé par l'API */} | null,
error: null | {
message: string,
code: string, // 'HTTP_503', 'ETIMEDOUT', 'PARTIAL_FAILURE', …
retryable: boolean,
attempts: number,
details?: unknown,
},
}Le schéma de traitement est toujours le même : on teste res.ok, jamais un try/catch.
const res = await SpmCustomers.list(client, { limit: 50 });
if (!res.ok) {
throw new Error(res.error.message); // rien n'est "throw" par le SDK : on teste res.ok
}
console.log(res.data.data); // ⚠️ payload métier double-niché : res.data.dataLe payload métier est à res.data.data
L'API ShopiMind enveloppe elle-même ses réponses sous la forme { statusCode, data }. Le SDK place ce corps complet dans envelope.data. Le payload métier se trouve donc à res.data.data — c'est volontaire, ne le confondez pas avec res.data.
À propos de SpmClientException
Le SDK exporte une classe SpmClientException, levée sur les erreurs de configuration (par exemple un baseUrl invalide passé à getClient), mais jamais sur un échec HTTP (qui part dans l'enveloppe).
Lire des données
Les méthodes de lecture sont statiques et prennent le client en premier argument. La query est sérialisée en chaîne de requête.
// Liste paginée
const page = await SpmCustomers.list(client, { limit: 50, offset: 0 });
// Un élément par identifiant (+ projection de champs optionnelle)
const customer = await SpmCustomers.get(client, 'cust_1', ['email', 'first_name']);
const order = await SpmOrders.get(client, 'ord_123');
const byRef = await SpmOrders.getByReference(client, 'CMD-2024-0001');
// Sous-ressources d'un parent
const addresses = await SpmCustomersAddresses.list(client, 'cust_1', { limit: 20 });
const groups = await SpmCustomers.listGroups(client, 'cust_1');Écrire des données
Statique — opérations en lot (recommandé pour la synchro)
Pour pousser des volumes, utilisez les méthodes en lot. L'option { chunk: true } découpe automatiquement un tableau en requêtes successives (voir Résilience pour les tailles de lot par ressource).
// Écriture en lot avec découpage automatique
const saved = await SpmCustomers.bulkSave(client, customers, { chunk: true });
await SpmCustomers.bulkUpdate(client, customers, { chunk: true });
await SpmCustomers.delete(client, 'cust_1');
await SpmCustomers.bulkDelete(client, ['cust_1', 'cust_2']);bulkDelete est un POST
bulkDelete envoie un POST vers …/bulk-delete (et non une requête DELETE).
Instance — un item à la fois
Chaque ressource expose aussi une forme « instance ». Vous instanciez l'objet avec le client, vous renseignez les champs, puis vous appelez .save() ou .update().
import { SpmCustomers } from '@shopimind/sdk-js';
const customer = new SpmCustomers(client);
customer.customer_id = 'cust_1';
customer.email = 'foo@bar.com';
customer.first_name = 'Foo';
customer.last_name = 'Bar';
customer.lang = 'fr';
customer.is_active = true;
customer.created_at = '2026-01-01T00:00:00Z';
customer.updated_at = '2026-01-01T00:00:00Z';
const res = await customer.save(); // ou .update()Forme envoyée par .save() / .update()
.save() (POST) et .update() (PUT) envoient l'objet emballé dans un tableau[data]. De plus, .update() compacte le payload : les champs valant null, undefined, '', 0, false ou [] sont silencieusement omis. Si vous devez mettre à jour un champ vers 0, false ou '', passez plutôt par bulkUpdate.
Ressources imbriquées (addresses, images, variations)
Pour les sous-ressources d'un parent, le constructeur prend le parent, et les méthodes statiques prennent l'identifiant du parent en 2ᵉ argument :
import { SpmCustomersAddresses } from '@shopimind/sdk-js';
await SpmCustomersAddresses.bulkSave(client, 'cust_1', addresses, { chunk: true });
await SpmCustomersAddresses.bulkDelete(client, 'cust_1', ['42', '43']);Endpoint plat bulkSaveAll
Certaines ressources imbriquées exposent un bulkSaveAll qui accepte un payload plat, avec le parent embarqué dans chaque élément (lot multi-parents) :
await SpmCustomersAddresses.bulkSaveAll(client, [
{ customer_id: 'cust_1', address_id: 1, /* … */ },
{ customer_id: 'cust_2', address_id: 2, /* … */ },
], { chunk: true });Associer une source de données (id_data_source / source_label)
Les entités synchronisables acceptent en option un identifiant ou un libellé de source de données. C'est utile pour distinguer plusieurs origines (par exemple un point de vente en plus du site e-commerce).
customer.id_data_source = 3;
customer.source_label = 'Magasin Paris';
await customer.save();Vous construisez une intégration ?
Au sein d'une intégration bâtie avec le kit, vous ne créez pas le client vous-même : le kit le construit pour vous et l'expose comme ctx.spm (un SpmHttpClient, le client SDK direct). Voir le guide Synchroniser ses données.
Enregistrer une boutique
SpmShopConnection.saveConfiguration envoie la configuration de la boutique (POST shop/connection).
import { SpmClient, SpmShopConnection } from '@shopimind/sdk-js';
const client = SpmClient.getClient('v1', process.env.SHOPIMIND_API_KEY!);
await SpmShopConnection.saveConfiguration(client, {
default_currency: 'EUR',
default_lang: 'fr',
langs: ['fr', 'en'],
timezone: 'Europe/Paris',
url_client: 'https://maboutique.example.com',
ecommerce_version: '2.7.0',
module_version: '5.0.0',
});Et ensuite
- Résilience (réessais, découpage en lots, helpers) — comment fonctionnent le chunking et les retries.
- Ressources — la table complète des ressources, méthodes et endpoints.
- Types TypeScript — les DTO exacts pour typer vos payloads.