Documentation pour les développeurs
Intégrez les données produits de saneq à vos assistants IA, comparateurs et services partenaires. Cette page présente les accès au catalogue, les clés API et les moyens de préparer un panier que vos clientes et clients pourront vérifier avant de finaliser leur achat.
Découverte des ressources
- robots.txt indique les consignes destinées aux robots et l’emplacement du sitemap.
- sitemap.xml répertorie les sitemaps des langues publiées dans la boutique.
- /.well-known/ai-catalog.json décrit les ressources exploitables par une machine. Il est signalé par l’en-tête Link avec rel="ai-catalog".
- /.well-known/ard.json fournit le même catalogue sous un alias, avec une valeur Link supplémentaire rel="ard", conformément au projet ARD v0.91.
- llms.txt résume l’assortiment, les services et les accès aux données.
- Les pages produits et catégories contiennent du JSON-LD avec des données structurées sur les produits, leurs prix et leur disponibilité.
API produits
L’API publique a pour adresse de base https://api.saneq.ch. La lecture est anonyme et ne nécessite aucune clé API. Les points d’accès GET ci-dessous renvoient du JSON.
GET /shop/products: rechercher et filtrer les produits, avec des résultats paginés.GET /shop/products/{titleSlug}[/{variantSlug}]: consulter une fiche produit ou une variante précise. La partie entre crochets est facultative.GET /shop/products/{titleSlug}/reviews: lire les avis sur un produit.GET /shop/categories/by-path/{pfad}: retrouver une catégorie à partir de son chemin.GET /categories/tree: obtenir l’arborescence des catégories.GET /shop/brands: consulter la liste des marques.GET /shop/store-policy: récupérer les informations de retour et d’expédition dans un format structuré.
Construire une requête
Pour les listes de produits, utilisez q pour le texte recherché, categorySlug pour la catégorie, brand ou brandId pour la marque, et priceMin et priceMax pour les prix. Les filtres inStock, attr et range portent respectivement sur le stock, les attributs et les plages de valeurs. page choisit la page, pageSize le nombre de résultats, limité à 100 par page, et sort l’ordre de tri.
Le paramètre lang=de|fr|it|en sélectionne la langue ; son absence équivaut à l’allemand. Les slugs utilisés pour les produits et les catégories doivent correspondre à la langue demandée.
Exemple : https://api.saneq.ch/shop/products?q=tape&inStock=true&page=1&pageSize=20&lang=fr
Lire les réponses
Les prix sont exprimés en CHF, taxes comprises. Les champs dont le nom se termine par Minor utilisent les unités mineures, soit les centimes : 1290 représente CHF 12.90. descriptionPlain fournit une description sans HTML. Les éléments de specs comprennent notamment rawValue et unitCode, pour les valeurs d’attributs et leurs unités. Le champ availability décrit la disponibilité. Les réponses de détail produit comportent un en-tête Cache-Control public.
Serveur MCP
Connectez un client prenant en charge les serveurs MCP distants, par exemple Claude Desktop ou un connecteur ChatGPT compatible, à https://api.saneq.ch/mcp. Utilisez le transport Streamable HTTP sans authentification : le catalogue ne nécessite ni connexion à un compte ni clé API.
search_productsrecherche dans le catalogue par texte, catégorie ou marque et renvoie au maximum 20 résultats par page, avec une pagination commençant à 0.get_productfournit, à partir du slug d’un produit et éventuellement d’une variante, les détails, les caractéristiques, le prix TTC, la disponibilité et l’URL du produit.check_availabilityvérifie la disponibilité, le prix TTC et le délai de livraison pour un maximum de 50 identifiants de produits et signale séparément les identifiants introuvables.list_categoriesrépertorie les catégories publiques avec leur chemin et leur nombre de produits dans la langue demandée.get_store_policyfournit les conditions actuelles de retour, d’expédition et de livraison.
Les ressources JSON saneq://store-policy et saneq://categories fournissent les conditions commerciales et les catégories. La ressource des catégories est en allemand ; utilisez list_categories pour les autres langues. Le prompt recommend_product aide à recommander des produits selon un besoin, un budget facultatif en CHF et une langue.
L’accès distinct aux paniers https://api.saneq.ch/mcp/cart utilise également Streamable HTTP. Authentifiez-vous avec Authorization: Bearer sk_… et une clé API dotée du scope cart:write. Il propose create_cart(items[{productId, quantity}], locale?, buyerEmail?), get_cart(cartId) et update_cart(cartId, items), ainsi que les cinq outils de lecture de /mcp. Aucun outil ne permet de finaliser un achat : continue_url est le seul moyen d’accéder à la caisse, où la cliente ou le client termine son achat dans la boutique. Citez les prix et la disponibilité uniquement à partir des résultats des outils.
Clés API
Une clé API avec le scope cart:write est obligatoire pour l’API de paniers pour agents et l’accès MCP distinct aux paniers. L’API publique de produits, le catalogue MCP, les liens directs vers un panier et l’API de transfert sont accessibles anonymement, sans clé API.
Demandez une clé à [email protected] en décrivant votre intégration, les scopes nécessaires et le volume de requêtes prévu. L’équipe saneq crée et gère les clés dans l’administration.
Transmettez la clé dans l’un des deux en-têtes HTTP : Authorization: Bearer sk_… ou X-Api-Key: sk_…. Conservez-la dans votre intégration côté serveur et ne la transmettez pas dans des liens publics.
catalog:readcorrespond à la lecture du catalogue avec une clé ; les accès anonymes au catalogue restent utilisables sans clé.cart:writepermet de créer, lire, modifier et annuler les paniers du client API concerné ; ce scope ne permet pas de finaliser un achat.
Les requêtes au catalogue et à l’API de paniers pour agents sont soumises à une limite par minute configurée pour chaque client API et sa clé, fixée par défaut à 600 requêtes par minute. La limite convenue pour votre clé fait référence. Le renouvellement de la clé ne réinitialise pas ce quota.
Demandez à l’équipe saneq de renouveler ou de révoquer vos clés dans l’administration selon vos besoins. Lors d’un renouvellement, la nouvelle clé remplace l’ancienne ; mettez votre intégration à jour en conséquence. La clé complète n’est communiquée qu’une seule fois, lors de sa création ou de son renouvellement.
Préparer un panier pour vos clients
Ces accès préparent un panier. La cliente ou le client vérifie les articles, les ajoute à son panier dans la boutique et finalise lui-même son achat. Sans cette étape, aucune commande ni aucun paiement n’est déclenché. Les articles, jetons et montants ci-dessous sont des exemples fictifs ; utilisez les identifiants et SKU du catalogue actuel.
Lien direct : utilisez le format /warenkorb?add=SKU:qty,SKU:qty avec au maximum 20 lignes et des quantités entières de 1 à 99. Aucune clé API n’est nécessaire. Exemple en français :
https://www.saneq.ch/fr/panier?add=ART-123:2,ART-456:1
Les chemins localisés sont /fr/panier?add=SKU:qty,…, /it/carrello?add=SKU:qty,… et /en/cart?add=SKU:qty,…. Le lien permet de vérifier les articles proposés avant de les ajouter au panier.
API de transfert : POST /shop/cart/handoff crée anonymement un lien de transfert à partir de items et de locale (de, fr, it ou en). Chaque ligne contient soit un productId numérique, soit un sku, ainsi que quantity. La requête accepte de 1 à 50 lignes et des quantités de 1 à 999.
Exemple de requête :
POST https://api.saneq.ch/shop/cart/handoff
Content-Type: application/json
{
"items": [
{
"sku": "ART-123",
"quantity": 2
}
],
"locale": "fr"
}
Exemple de réponse ; skipped indique les lignes omises :
HTTP/1.1 201 Created
{
"token": "bW9ja19oYW5kb2ZmX3Rva2VuXzMyX2J5dGVzXzAwMDA",
"continueUrl": "https://www.saneq.ch/fr/panier/reprendre/bW9ja19oYW5kb2ZmX3Rva2VuXzMyX2J5dGVzXzAwMDA",
"expiresAtUtc": "2026-10-14T10:00:00Z",
"skipped": []
}
Transmettez la continueUrl reçue à la cliente ou au client. GET /shop/cart/handoff/{token} affiche les articles avec leurs prix et leur disponibilité actuels. Après confirmation, la boutique les ajoute au panier avec POST /shop/cart/handoff/{token}/redeem et le X-Cart-Key du panier destinataire. Une nouvelle utilisation du même jeton dans ce panier n’ajoute pas les quantités une seconde fois ; les jetons inconnus ou expirés renvoient 404.
API de paniers pour agents selon ACP-Cart : l’adresse de base est https://api.saneq.ch/agent/carts. Tous les appels nécessitent une clé API avec cart:write et portent sur les paniers de ce client API.
POST /agent/cartscrée un panier et renvoie 201.GET /agent/carts/{id}lit le panier avec les prix et la disponibilité actuels.PUT /agent/carts/{id}remplace toutes les lignes par la liste fournie.POST /agent/carts/{id}/cancelannule le panier de l’agent ; les liens de transfert déjà émis restent valables jusqu’à leur expiration.
Envoyez API-Version: 2026-04-17 pour les quatre opérations. La création et l’annulation nécessitent aussi un Idempotency-Key de 1 à 128 caractères ASCII imprimables : choisissez une nouvelle valeur pour chaque nouvelle opération et réutilisez-la lorsque vous répétez la même requête. PUT ne nécessite pas cet en-tête. line_items contient de 1 à 50 lignes avec un id au format v{productId} et une quantity de 1 à 999.
Exemple de création ; remplacez la clé d’exemple par la vôtre :
POST https://api.saneq.ch/agent/carts
Authorization: Bearer sk_…
API-Version: 2026-04-17
Idempotency-Key: cart-demo-001
Content-Type: application/json
{
"line_items": [
{
"id": "v12345",
"quantity": 2
}
],
"locale": "fr"
}
Extrait d’une réponse d’exemple :
HTTP/1.1 201 Created
API-Version: 2026-04-17
{
"id": "f268c6ea-89af-4183-a426-b75bdcaa32c5",
"line_items": [
{
"id": "line_12345",
"item": {
"id": "v12345",
"name": "Produit d’exemple",
"unit_amount": 1290
},
"quantity": 2,
"totals": [
{
"type": "subtotal",
"amount": 2580
}
]
}
],
"currency": "chf",
"totals": [
{
"type": "subtotal",
"amount": 2580
},
{
"type": "shipping",
"amount": 790
},
{
"type": "total",
"amount": 3370
}
],
"continue_url": "https://www.saneq.ch/fr/panier/reprendre/bW9ja19oYW5kb2ZmX3Rva2VuXzMyX2J5dGVzXzAwMDA"
}
unit_amount et totals[].amount sont des nombres entiers en unités mineures : avec currency: "chf", 1290 correspond à CHF 12.90. Les prix des produits incluent la TVA ; les frais de livraison sont estimatifs. Consultez les informations de messages et transmettez la continue_url actuelle à la cliente ou au client. Cette API ne permet pas de finaliser un achat.
Conditions commerciales
GET /shop/store-policy expose les informations de retour et d’expédition sous une forme lisible par machine : délai et mode de retour, frais et délais de livraison. Appuyez votre intégration sur ces données et tenez compte des exclusions de retour propres à certains produits.
Utilisation raisonnable (Fair Use)
- Les requêtes anonymes au catalogue sont soumises à la limite
catalog-readde 300 requêtes par minute et par adresse IP. Évitez les répétitions inutiles et les pics de charge ; avec une clé API, la limite individuelle par minute s’applique. - En cas de dépassement, vous recevez HTTP 429. Attendez le nombre de secondes indiqué dans l’en-tête
Retry-Afteravant de réessayer. - Respectez les en-têtes
Cache-Controlet réutilisez les réponses pendant leur durée de validité. Les détails des produits utilisent par exemplepublic, max-age=300, stale-while-revalidate=3600. Les réponses avecprivate, no-store, notamment les transferts de panier, ne doivent pas être mises en cache. - Mentionnez « saneq.ch » comme source des données utilisées.
- Les prix et la disponibilité peuvent évoluer. Les prix affichés en dehors de la boutique ne sont pas garantis ; les indications de la boutique font référence.
- Pour toute question sur une intégration, écrivez à [email protected].
Pour répéter une tentative de commande lors du passage en caisse du client, POST /shop/checkout/orders prend en charge l’en-tête Idempotency-Key de 1 à 128 caractères ASCII imprimables. Utilisez la même clé pour le même panier et le même corps de requête, par exemple après une interruption de connexion.
- Une répétition renvoie la réponse enregistrée avec
Idempotent-Replayed: true. - Si la clé est réutilisée avec un autre panier ou une autre requête, la réponse est HTTP 422 avec
checkout.idempotency-mismatch. - Si la première tentative est encore en cours, la réponse est HTTP 409 avec
checkout.idempotency-in-progressetRetry-After: 2; répétez la requête identique après ce délai.
L’idempotence au passage en caisse évite les tentatives de commande en double ; elle n’autorise pas les agents à finaliser un achat sans la cliente ou le client.