Introduction
Le Search API expose le moteur Heurix : un moteur de recherche pensé pour les catalogues techniques, où les requêtes et les fiches produits traversent le même pipeline — normalisation (casse, accents), synonymes métier, tolérance aux fautes de frappe, puis une cascade de règles qui transforme le texte en annotations structurées. C'est cette cascade qui permet à m8x20 de retrouver une fiche enregistrée « M8 x 20 — A2 ».
L'API est REST, en JSON, sur HTTPS uniquement. Toutes les réponses sont encodées en UTF-8.
Démarrage rapide
Trois appels suffisent pour une première recherche fonctionnelle.
1 Indexez vos produits (le catalogue est créé automatiquement au premier envoi) :
curl -X POST https://api.heurix.fr/v1/index/moncatalogue/items \
-H "Authorization: Bearer VOTRE_CLE_API" \
-H "Content-Type: application/json" \
-d '{
"rulepack": "outillage",
"items": [
{"id": "V1", "name": "Vis tête hexagonale", "ref": "M8 x 20 — A2", "stock": 100},
{"id": "V2", "name": "Vis tête hexagonale", "ref": "M8 x 30 — A2", "stock": 50}
]
}'
2 Cherchez — les fautes de frappe sont tolérées :
curl -X POST https://api.heurix.fr/v1/index/moncatalogue/search \
-H "Authorization: Bearer VOTRE_CLE_API" \
-H "Content-Type: application/json" \
-d '{"q": "m8x20 inox"}'
3 Lisez la réponse — chaque résultat explique pourquoi il correspond :
{
"query": "m8x20 inox",
"total": 2,
"hits": [
{
"product": {"id": "V1", "name": "Vis tête hexagonale", "ref": "M8 x 20 — A2", "stock": 100},
"score": 37.5,
"in_stock": true,
"matched": ["annotation #VIS_M8X20", "annotation #DIAM_M8", "annotation #LONG_20"]
}
]
}
Authentification
Chaque appel doit porter votre clé API dans l'en-tête Authorization :
Authorization: Bearer VOTRE_CLE
Une clé manquante ou mal formée renvoie 401 ; une clé invalide ou hors de sa portée renvoie 403.
Deux types de clés
Le choix n'est pas cosmétique : il détermine ce qu'un tiers peut faire s'il met la main sur votre clé.
| Type | Préfixe | Portée | Où l'utiliser |
|---|---|---|---|
| Clé serveur | hx_ |
Accès complet : indexation, merchandising, statistiques, facturation | Côté serveur uniquement. Jamais dans une page web. |
| Clé publique | hxp_ |
Recherche, parcours de catalogue, événements de conversion — rien d'autre | Navigateur, applications mobiles, tout contexte où la clé est visible |
Une clé publique appelant un endpoint hors de sa portée reçoit un 403 explicite. Elle partage le quota de la clé serveur qui l'a générée — en créer plusieurs n'augmente donc pas vos plafonds.
Générer une clé publique
Depuis votre console (Mes infos → Ma clé API), ou par API avec votre clé serveur :
curl -X POST https://api.heurix.fr/v1/keys/public \
-H "Authorization: Bearer VOTRE_CLE_SERVEUR" \
-H "Content-Type: application/json" \
-d '{"allowed_origins": "monsite.fr,www.monsite.fr"}'
allowed_origins est optionnel mais recommandé : la clé n'est alors acceptée que depuis les domaines listés, ce qui la rend inutilisable si quelqu'un la recopie sur un autre site. GET /v1/keys/public les liste, DELETE /v1/keys/public/{clé} en révoque une.
⚠️ Les clés existantes restent des clés serveur et continuent de fonctionner à l'identique — rien ne casse. Mais si vous en avez posé une dans le JavaScript de votre site (barre de recherche, tracker, widget Browse), remplacez-la par une clé publique : en l'état, n'importe quel visiteur peut la lire et accéder à votre facturation.
Comptage des requêtes
La facturation repose sur un compteur mensuel de requêtes, simple par principe :
| Recherche | 1 appel search = 1 requête |
| Indexation | jamais décomptée du quota de requêtes — mettez à jour votre catalogue aussi souvent que nécessaire, seul le nombre total de produits indexés reste plafonné par plan |
| Recherche fédérée | 1 requête par catalogue interrogé |
| Gestion | Chaque autre appel API (synonymes, stats, suppression...) = 1 requête |
| Dépassement (Scale) | Le surplus est facturé au tarif indiqué sur la page tarifs — jamais de coupure |
| Dépassement (autres plans) | Une marge de tolérance de 10 % absorbe un pic ponctuel ; au-delà, la requête est refusée avec un code 429 explicite |
Votre consommation en cours est consultable à tout moment via GET /v1/usage.
Plans et plafonds
Chaque clé API est rattachée à un plan qui définit son volume de requêtes mensuelles, son nombre de produits indexables, et son nombre de catalogues. Le détail des fonctionnalités de chaque plan est sur la page tarifs ; voici les plafonds bruts :
| Plan | Requêtes / mois | Produits max | Catalogues |
|---|---|---|---|
| Essai (14 jours) | 2 000 | 2 000 | 2 |
| Starter — 19 €/mois | 15 000 | 8 000 | 1 |
| Growth — 49 €/mois | 30 000 | 25 000 | 3 |
| Scale — 139 €/mois | 150 000 puis facturé | 100 000 | illimité |
Passé les 14 jours d'essai sans souscription à un plan payant, une clé repasse automatiquement aux plafonds de l'essai jusqu'à souscription — vos catalogues et leur configuration restent intacts, simplement moins accessibles en volume le temps de passer à un plan payant.
Un dépassement de plafond renvoie un code 429 avec le détail de la cause :
{
"detail": "Plafond de requêtes du plan 'starter' dépassé (5 512/5 000, marge de 10% également dépassée). Passez à un plan supérieur pour continuer.",
"plan": "starter",
"limit_type": "requests",
"upgrade_url": "https://heurix.fr/pricing.html"
}
Structure des produits
Un produit est un objet JSON libre. Quatre champs ont un rôle particulier :
| Champ | Type | Rôle |
|---|---|---|
id | string requis | Identifiant unique dans le catalogue. Ré-indexer le même id remplace le produit (upsert). |
ref | string | Référence produit (SKU, code fabricant). Indexée, poids le plus fort. |
name | string | Nom du produit. Indexé, poids fort. |
description | string | Description. Indexée, poids standard. |
stock | number | bool | string | Disponibilité — utilisée pour le tri à pertinence égale. 0, false, "rupture" = indisponible. |
Tout autre champ (prix, image, URL, catégorie...) est stocké tel quel et restitué dans les résultats, sans être indexé.
/v1/index/{catalog}/searchRecherche
Lance une recherche sur un catalogue. Résultats triés par pertinence, puis disponibilité à score égal. Une requête vide (q: "") est acceptée : c'est le mode parcours, pour naviguer un catalogue par facettes seules, avant toute saisie texte.
Corps de la requête
| Paramètre | Type | Description |
|---|---|---|
q | string | La requête de recherche (0 à 500 caractères — vide autorisé, voir mode parcours ci-dessus). |
limit | integer | Nombre de résultats par page (1–100, défaut 10). |
offset | integer | Décalage de pagination (défaut 0). |
facets | array de string | Groupes d'annotations pour lesquels renvoyer un décompte (ex. ["PAYS", "FORMAT"]). Voir Facettes et filtres. |
filters | array de string | Annotations exactes exigées, combinées en ET (ex. ["PAYS_SE", "FORMAT_PO"]). |
Réponse
total (nombre de correspondances), hits — chaque hit contient le product complet tel qu'indexé, son score, in_stock, et matched : la liste lisible des raisons de la correspondance (termes trouvés, fautes corrigées, annotations partagées) — utile pour comprendre et régler la pertinence. Si facets a été demandé, un champ facets supplémentaire liste les décomptes par groupe.
Simulation de règles côté Browse
/v1/browse/{catalog}/{category}/simulatePendant du champ simulate_overrides de la recherche, pour le merchandising de catégorie. Prévisualise un classement avec des règles non enregistrées :
{
"overrides": [{"product_id": "PER-BOSCH-18V", "action": "pin", "position": 1}],
"sort": "stock",
"limit": 20
}
Endpoint dédié en POST plutôt qu'un paramètre sur le GET existant : une liste de règles provisoires dépasse vite la longueur raisonnable d'une URL, et cela laisse le chemin de lecture normal totalement intact.
| Garantie | Comportement |
|---|---|
| Écriture en base | Aucune. Vos règles enregistrées sont inchangées. |
| Quota Browse | Non consommé. Ce sont vos tests, pas du trafic client. |
| Clé requise | Clé serveur. Une clé publique reçoit un 403. |
| Règles par attribut | Celles enregistrées continuent de s'appliquer — la simulation porte sur le merchandising par produit, pas sur la configuration du catalogue. |
overrides remplace l'ensemble persisté pour cet appel. Une liste vide prévisualise donc « sans aucune règle », ce qui permet de voir l'effet d'une suppression avant de la faire.
Simulation de règles
Tester une priorité de requête obligeait à l'enregistrer — donc à l'appliquer immédiatement à vos visiteurs. Le champ simulate_overrides permet de voir l'effet sans rien écrire :
{
"q": "vis",
"simulate_overrides": [
{"query": "vis", "product_id": "PER-BOSCH-18V", "action": "pin", "position": 1}
]
}
La réponse porte "simulated": true, et les résultats sont classés comme si ces règles étaient actives.
La liste remplace l'ensemble de vos priorités enregistrées pour cet appel — elle ne s'y ajoute pas. C'est ce qui permet de prévisualiser aussi bien un ajout qu'une modification ou une suppression : il suffit d'envoyer l'état voulu complet. Une liste vide prévisualise donc « sans aucune règle ».
| Garantie | Comportement |
|---|---|
| Écriture en base | Aucune. Vos priorités enregistrées sont inchangées. |
| Quota | Non consommé. Ce sont vos tests sur votre catalogue, pas des recherches de vos clients. |
| Statistiques de recherche | Non journalisé. Vos essais ne polluent pas vos propres analyses. |
| Clé requise | Clé serveur uniquement. Une clé publique reçoit un 403 — c'est un outil d'administration, pas du trafic visiteur. |
Contraintes de prix en langage naturel
Une contrainte de prix formulée en français est reconnue dans la requête et convertie en filtre — « vis inox moins de 5 € » filtre sur le prix au lieu de chercher les mots « moins » et « euros » dans votre catalogue.
{"query": "vis inox", "total": 3, "hits": [...],
"price_filter": {"min": null, "max": 5.0}}
La requête renvoyée est débarrassée du fragment consommé (« vis inox », et non « vis inox moins de 5 € ») : les mots de la contrainte ne pèsent pas sur le score de pertinence. Le champ price_filter n'apparaît que si une contrainte a été détectée — utile pour l'afficher à l'acheteur et lui permettre de la retirer.
Formulations reconnues — liste volontairement courte et documentée plutôt qu'exhaustive :
| Effet | Tournures |
|---|---|
| Prix maximum | moins de X, inférieur à X, sous X €, en dessous de X, jusqu'à X €, max X € |
| Prix minimum | plus de X, supérieur à X, au-dessus de X, à partir de X €, min X € |
| Intervalle | entre X et Y € |
Le symbole € et le mot « euros » sont optionnels sur la plupart des tournures. La virgule décimale française est acceptée (3,50 comme 3.50).
Un produit sans champ price est exclu dès qu'une contrainte est active : on ne peut pas affirmer qu'il la respecte, et le faire remonter serait trompeur. Il reste trouvable par une recherche sans contrainte de prix.
Recherche en train d'être tapée
Un mot de 3 caractères ou plus qui correspond au début d'un mot du vocabulaire remonte aussi des résultats — pas seulement une correspondance exacte ou une faute de frappe complète. Taper « per » retrouve déjà « perceuse », sans attendre le mot entier. Un résultat trouvé par ce biais compte toujours moins qu'une correspondance exacte ou une faute de frappe classique : dès que la requête est complète, le classement se réajuste vers les résultats les plus pertinents. En dessous de 3 caractères, aucune correspondance par préfixe n'est tentée — trop de mots du vocabulaire partageraient un début de 1 ou 2 lettres par pur hasard.
Secours sur zéro résultat
Une recherche qui ne trouve rien (total: 0) sur un catalogue contenant au moins un produit marqué featured: true à l'indexation renvoie jusqu'à 6 de ces produits dans hits, avec fallback: true — pour proposer une porte de sortie plutôt qu'une page vide. total reste à 0 : ce ne sont pas de vrais résultats de recherche, à vous de les présenter distinctement côté front (ex. « Aucun résultat pour "…" — nos incontournables » plutôt que de les mélanger à de vrais résultats). Sans produit featured dans le catalogue, hits reste vide et fallback vaut false, comme avant.
Catégorie suggérée
Si un mot de la requête (4 caractères ou plus) recoupe une catégorie Browse connue de ce catalogue, la réponse inclut un champ suggested_category — une piste pour proposer « vous cherchez sans doute dans telle catégorie ? » côté interface, jamais un filtre automatique : le tri et le contenu de hits restent inchangés.
{"query": "perceuse", "total": 4, "hits": [...],
"suggested_category": {"category": "perceuses-visseuses", "products": 12}}
La correspondance se fait par sous-chaîne, pas seulement une égalité stricte — « perceuse » (singulier) retrouve bien la catégorie « perceuses-visseuses » (pluriel, avec tiret). Si plusieurs catégories correspondent à la fois, la plus peuplée l'emporte. Absent de la réponse s'il n'y a aucune correspondance, ou en mode parcours (requête vide).
/v1/index/{catalog}/search-overridesPriorités de requête
Épinglez ou reléguez un produit quand une recherche contient un mot précis — « si la recherche contient promo, tel produit apparaît en premier ». Indépendant de Browse & Discovery, qui classe des catégories de navigation, pas des requêtes de recherche.
curl -X POST https://api.heurix.fr/v1/index/moncatalogue/search-overrides \
-H "Authorization: Bearer VOTRE_CLE_API" \
-H "Content-Type: application/json" \
-d '{"query": "promo", "product_id": "sku-123", "action": "pin", "position": 1}'
Déclenchement par sous-séquence contiguë, pas seulement une correspondance exacte : une règle posée sur "promo" se déclenche pour "vis promo" ou "grosse promo inox", mais pas pour "promotionnel" (mot différent une fois normalisé). Un pin peut faire apparaître un produit qui ne matche pas textuellement la requête — c'est le point de cette fonctionnalité, pas un bug.
| Champ | Type | Description |
|---|---|---|
query | string | Le déclencheur, normalisé comme le reste du moteur (accents, casse) avant comparaison. |
product_id | string | Le produit concerné. |
action | string | pin (position exacte, requiert position) ou bury (fin de liste, ne s'applique qu'à un produit déjà présent naturellement). |
position | entier | Le rang final du produit, à partir de 1. position: 3 le place en 3e position ; les autres produits comblent les places restées libres dans leur ordre naturel. Deux produits demandant le même rang sont placés côte à côte. Un rang supérieur au nombre de résultats ramène le produit en fin de liste. |
GET /v1/index/{catalog}/search-overrides liste toutes les règles du catalogue (ou celles d'une requête précise avec ?query=...) ; DELETE /v1/index/{catalog}/search-overrides?query=...&product_id=... en retire une. Aucun de ces trois appels ne consomme le quota — ce sont des actions de configuration, pas des requêtes de recherche.
Facettes et filtres
Une facette regroupe les annotations qui partagent un même préfixe — PAYS_SE et PAYS_FR appartiennent au groupe PAYS. Demandez un décompte par groupe avec facets, restreignez les résultats avec filters :
curl -X POST https://api.heurix.fr/v1/index/moncatalogue/search \
-H "Authorization: Bearer VOTRE_CLE_API" \
-d '{"q": "polar", "facets": ["PAYS", "FORMAT"], "filters": ["PAYS_SE"]}'
{
"total": 12,
"hits": [ ... ],
"facets": {
"PAYS": {"PAYS_SE": 12, "PAYS_FR": 34, "PAYS_UK": 9},
"FORMAT": {"FORMAT_PO": 8, "FORMAT_BR": 4}
}
}
Le décompte est disjonctif au sein d'un même groupe : filtrer sur PAYS_SE ne fait pas disparaître PAYS_FR du décompte — c'est ce qui permet d'afficher « France (34) » comme option alternative même une fois la Suède sélectionnée, exactement comme un filtre de boutique en ligne classique. Entre deux groupes différents, en revanche, les filtres restent cumulatifs (ET logique).
/v1/browse/{catalog}/{category}Browse & Discovery
Classe tous les produits d'une catégorie sans requête — pour une page de listing (catégorie, rayon), pas une barre de recherche. Remplace un tri statique par un classement configurable, enrichi par vos propres priorités manuelles.
{category} est un champ que vous fournissez à l'indexation — exactement comme name ou stock, jamais dérivé d'un pack de règles. Ajoutez categories (une liste — un produit peut appartenir à plusieurs catégories à la fois, utile pour lister aussi bien la catégorie que ses ancêtres) ou category (une valeur unique) à vos produits :
🚀 Pas envie d'écrire l'appel fetch vous-même ? Téléchargez le snippet prêt à l'emploi — un guide pas à pas avec exemple complet est disponible sur le blog.
curl -X POST https://api.heurix.fr/v1/index/moncatalogue/items \
-H "Authorization: Bearer VOTRE_CLE_API" \
-H "Content-Type: application/json" \
-d '{"items": [{"id": "sku-123", "name": "Perceuse GDX 18V-285",
"categories": ["outillage-electroportatif", "perceuses-visseuses"],
"price": 139.90, "margin": 28.50, "stock": 8}]}'
curl "https://api.heurix.fr/v1/browse/moncatalogue/perceuses-visseuses?sort=price_asc" \
-H "Authorization: Bearer VOTRE_CLE_API"
| Paramètre | Type | Description |
|---|---|---|
sort | string | stock (défaut) · recent · alphabetical · price_asc / price_desc (lit le champ price) · margin (lit le champ margin, la plus forte d'abord) · popular (voir ci-dessous) |
filters | string | "champ:valeur,champ2:valeur2" (ET logique) — affine sur n'importe quel attribut libre du produit (marque, couleur…), en plus de la catégorie. Tout champ texte non réservé devient automatiquement filtrable dès l'indexation, sans configuration. |
facets | string | "champ,champ2" — renvoie un décompte par valeur pour chaque champ demandé, disjonctif (filtrer sur une valeur d'un champ ne fait pas disparaître les autres valeurs de ce même champ du décompte, comme côté recherche). |
limit / offset | int | Pagination, comme pour la recherche. |
curl "https://api.heurix.fr/v1/browse/moncatalogue/perceuses-visseuses?filters=brand:Makita&facets=brand,color" \
-H "Authorization: Bearer VOTRE_CLE_API"
Un produit sans le champ demandé (pas de price pour un tri price_asc, par exemple) n'est jamais exclu ni ne fait planter l'appel — il se retrouve simplement en fin de liste, quel que soit le sens du tri.
Consomme le quota de requêtes, comme un appel de recherche — c'est un appel moteur au même titre.
Tri par popularité (clics + achats)
sort=popular s'appuie sur les événements réellement remontés par le Heurix Tracker — un achat compte pour 5, un clic sur un résultat de recherche pour 1. Un produit très cliqué mais jamais encore acheté reste donc visible dans le classement plutôt que totalement absent tant qu'aucune vente n'est remontée. Sans aucune donnée de tracking, tous les produits reviennent simplement dans l'ordre par défaut — l'appel ne plante jamais.
Merchandising manuel : épingler ou reléguer un produit
Indépendant du tri naturel : un produit épinglé (pin) apparaît à la position choisie en tête de liste quel que soit son stock, son prix ou sa popularité ; un produit relégué (bury) passe systématiquement en fin de liste. Utile pour mettre en avant une nouveauté ou masquer discrètement un produit en fin de vie sans le désindexer.
curl -X POST https://api.heurix.fr/v1/browse/moncatalogue/perceuses-visseuses/overrides \
-H "Authorization: Bearer VOTRE_CLE_API" \
-H "Content-Type: application/json" \
-d '{"product_id": "sku-123", "action": "pin", "position": 1}'
curl -X DELETE https://api.heurix.fr/v1/browse/moncatalogue/perceuses-visseuses/overrides/sku-123 \
-H "Authorization: Bearer VOTRE_CLE_API"
Ne consomme pas le quota — c'est une action de configuration, pas une requête. Une priorité posée sur un produit qui sort ensuite de la catégorie devient simplement sans effet, pas une erreur.
Boost ou relégation par attribut
Même principe que le merchandising manuel, mais pour tous les produits partageant un attribut plutôt qu'un par un — « boostez toute la marque Makita » plutôt qu'épingler chaque référence individuellement. Un boost ou une relégation par attribut positionne les produits concernés comme un groupe, trié entre eux selon le sort choisi ; ce n'est pas une position fixe (voir pin ci-dessus pour ça).
curl -X POST https://api.heurix.fr/v1/browse/moncatalogue/perceuses-visseuses/attribute-rules \
-H "Authorization: Bearer VOTRE_CLE_API" \
-H "Content-Type: application/json" \
-d '{"field": "brand", "value": "Makita", "action": "boost"}'
curl -X DELETE "https://api.heurix.fr/v1/browse/moncatalogue/perceuses-visseuses/attribute-rules?field=brand&value=Makita" \
-H "Authorization: Bearer VOTRE_CLE_API"
Ordre de priorité en cas de conflit, du plus fort au plus faible : épinglé (par produit) > relégué (par produit ou par attribut) > boosté (par attribut) > tri naturel. Une relégation, qu'elle soit posée par produit ou par attribut, l'emporte toujours sur un boost — un produit explicitement caché ne doit jamais être resurfacé par une règle de boost plus large qui le concernerait par ailleurs.
/v1/federated-searchRecherche fédérée
Interroge plusieurs catalogues en un seul appel et fusionne les résultats par pertinence — utile pour un site multilingue (un catalogue par langue) ou multi-marque. Les poids de score sont globaux au moteur, pas propres à un catalogue : les scores restent comparables entre catalogues, même avec des packs de règles différents.
Corps de la requête
| Paramètre | Type | Description |
|---|---|---|
catalogs | array de string requis | 1 à 10 noms de catalogues à interroger. |
q | string | La requête de recherche. |
limit / offset | integer | Pagination sur l'ensemble fusionné. |
Réponse
Identique à une recherche classique, avec un champ catalog ajouté à chaque hit pour identifier sa provenance, et catalogs_searched / catalogs_not_found pour repérer un nom de catalogue invalide.
curl -X POST https://api.heurix.fr/v1/federated-search \
-H "Authorization: Bearer VOTRE_CLE_API" \
-d '{"catalogs": ["boutique-fr", "boutique-en"], "q": "pull rouge"}'
Comptage : 1 requête par catalogue effectivement interrogé — une fédération sur 3 catalogues compte pour 3 requêtes, à l'image de l'indexation par tranche.
/v1/index/{catalog}/itemsIndexation
Ajoute ou met à jour des produits par lot (upsert sur id). Le catalogue est créé automatiquement s'il n'existe pas. Champ optionnel featured (booléen) : marque un produit comme candidat au secours affiché quand une recherche ne trouve rien — voir Recherche, secours sur zéro résultat.
Corps de la requête
| Paramètre | Type | Description |
|---|---|---|
items | array requis | 1 à 5 000 produits par appel. Chaque produit doit avoir un id. |
rulepack | string | Pack de règles à associer au catalogue (outillage, mode, industrie). Changer de pack ré-indexe le catalogue. |
Réponse
{"indexed": 2, "catalog": {"catalog": "moncatalogue", "products": 2, "terms": 11,
"annotations": 9, "rulepack": "outillage", "synonym_groups": 0}}
/v1/index/{catalog}/items/{id}Suppression
Retire un produit de l'index et du stockage. Renvoie 404 si l'identifiant est inconnu.
curl -X DELETE https://api.heurix.fr/v1/index/moncatalogue/items/V1 \
-H "Authorization: Bearer VOTRE_CLE_API"
/v1/index/{catalog}/synonymsSynonymes
Les synonymes métier étendent la recherche : « vis » peut retrouver « boulon ». GET lit les groupes en place, PUT les remplace intégralement. Les groupes qui partagent un terme sont fusionnés automatiquement.
curl -X PUT https://api.heurix.fr/v1/index/moncatalogue/synonyms \
-H "Authorization: Bearer VOTRE_CLE_API" \
-H "Content-Type: application/json" \
-d '{"groups": [["vis", "boulon", "visserie"], ["ecrou", "nut"]]}'
/v1/index/{catalog}/statsStatistiques
État du catalogue : nombre de produits, de termes indexés, d'annotations produites par la cascade, pack de règles actif, groupes de synonymes.
/v1/usageConsommation
Compteur de requêtes du mois en cours pour la clé appelante.
{"month": "2026-07", "requests": 1284}
/v1/rulepacksPacks de règles
Liste les packs disponibles sur votre instance, avec leur nombre de niveaux et de règles. Trois packs standards sont fournis : outillage (visserie, normes DIN/ISO, matières), mode (tailles, coloris, matières, familles), industrie (roulements, références normalisées). Des packs sur mesure pour votre catalogue peuvent être conçus en mission Simulateur ROI.
/v1/index/{catalog}/custom-rulesCustom Rules
Étend le pack de règles actif d'un catalogue, sans y toucher — une Custom Rule est propre à un seul catalogue, jamais partagée avec un autre compte. Deux gabarits, sans regex à écrire : keyword (une liste de mots équivalents déclenche tous la même étiquette) et prefix_number (un préfixe suivi d'un nombre devient une étiquette avec la valeur capturée, ex. RAL reconnaît « RAL 9010 » et « RAL9010 »). Effet immédiat : tous les produits déjà indexés sont ré-annotés dès la création de la règle. Jusqu'à 30 règles personnalisées par catalogue.
curl -X POST https://api.heurix.fr/v1/index/moncatalogue/custom-rules \
-H "Authorization: Bearer VOTRE_CLE_API" \
-H "Content-Type: application/json" \
-d '{"rule_type": "keyword", "label": "Cheville",
"keywords": ["placo", "cheville", "molly", "plaquo"]}'
curl -X POST https://api.heurix.fr/v1/index/moncatalogue/custom-rules \
-H "Authorization: Bearer VOTRE_CLE_API" \
-H "Content-Type: application/json" \
-d '{"rule_type": "prefix_number", "label": "Coloris RAL", "prefix": "RAL"}'
Gérable aussi bien par API que directement depuis la console, dans « Mon catalogue ».
/v1/eventsConversion & ROI
Remonte les clics et achats de votre site vers Heurix, pour mesurer le taux de clic sur vos recherches et le chiffre d'affaires — voire la marge — qui en découle. Deux types d'événement : search_click (un clic sur un résultat de recherche) et purchase (un ou plusieurs produits achetés, avec montant et marge optionnelle par produit).
curl -X POST https://api.heurix.fr/v1/events \
-H "Authorization: Bearer VOTRE_CLE_API" \
-H "Content-Type: application/json" \
-d '{"event_type": "search_click", "catalog": "moncatalogue",
"query": "cheville placo", "product_id": "sku-123"}'
curl -X POST https://api.heurix.fr/v1/events \
-H "Authorization: Bearer VOTRE_CLE_API" \
-H "Content-Type: application/json" \
-d '{"event_type": "purchase", "catalog": "moncatalogue",
"products": [{"id": "sku-123", "amount": 29.90, "margin": 8.50}]}'
Cet endpoint est conçu pour être appelé depuis le navigateur du visiteur final, sur votre propre site — pas depuis heurix.fr — d'où un CORS ouvert à toutes origines. Trois façons de le poser, de la plus complète à la plus simple :
- Heurix Tracker (recommandé) — un identifiant visiteur persistant, pour relier un clic à un achat ultérieur du même visiteur plutôt qu'une simple corrélation agrégée. Un seul script à poser site-wide, expose les mêmes fonctions que le snippet ci-dessous.
- Modèle de balise Google Tag Manager (fichier
.tpl, à importer dans Modèles → Modèles de balises → Importer) — compatible avec le tracker via un champ « Identifiant visiteur » optionnel - Snippet JavaScript simple, sans identifiant persistant — pour une intégration minimale sans GTM ni tracker
Ne consomme pas votre quota de requêtes — ce n'est pas un appel moteur, c'est une remontée de données.
⚠️ À savoir avant de lire vos chiffres : même avec le tracker, l'attribution recherche → achat n'est pas une garantie à 100 %. Sans identifiant visiteur, Heurix agrège les clics et achats reçus sur une même période et un même compte (total_revenue) — une corrélation, pas une preuve. Avec le tracker installé, un champ supplémentaire (attributed_revenue) ne compte que les achats où le même visiteur a cliqué depuis une recherche dans les 24 heures précédentes — un lien réel, nettement plus fiable, mais qui dépend toujours de la qualité de votre implémentation.
/v1/analytics/conversion-summaryTaux de clic, chiffre d'affaires et marge attribués sur la période (?days=30 par défaut). Renvoie aussi attributed_revenue et attributed_products — null si aucun événement de la période ne porte d'identifiant visiteur (le tracker n'est pas installé), un chiffre réel sinon.
/v1/analytics/top-productsProduits les plus achetés, triés par volume ou par marge (?sort_by=volume ou margin).
Vues de page de catégorie
Le tracker peut remonter les produits affichés sur une page de catégorie, ce qui permet de repérer ceux qui sont beaucoup montrés et peu cliqués — la population que l'épinglage et la relégation servent justement à corriger.
Heurix.trackCategoryView("visserie", ["sku-1", "sku-2", "sku-3"]);
Un seul appel par page vue, portant la liste des produits affichés — pas un appel par produit. Le moteur enregistre ensuite une impression par produit, ce qui rend l'agrégation possible en une requête. À savoir sur le volume : une page affichant 24 produits génère 24 lignes, purgées automatiquement au-delà de la période de rétention. La liste est plafonnée à 50 identifiants.
/v1/analytics/category-views/{catalog}Renvoie les catégories triées par nombre d'impressions, et dans chacune les produits les plus vus avec leur nombre de clics depuis la recherche. Ne consomme pas votre quota.
{"catalog": "moncatalogue", "categories": [
{"category": "visserie", "total_views": 512, "products": [
{"product_id": "sku-1", "views": 180, "search_clicks": 12},
{"product_id": "sku-2", "views": 175, "search_clicks": 0}
]}
]}
Renvoie une liste vide tant que le tracker ne remonte pas cet événement — c'est le cas de toute intégration antérieure à cette fonctionnalité. Rien ne casse, l'écran reste simplement vide.
Produits fréquemment achetés dans le même panier que {product_id} — une co-occurrence comptée, pas du machine learning. Utile pour une section « souvent acheté avec » sur une fiche produit.
{"product_id": "sku-123", "related": [
{"product_id": "sku-456", "co_purchases": 12},
{"product_id": "sku-789", "co_purchases": 4}
]}
Liste vide si moins de 5 achats sont enregistrés pour ce produit précis — pas assez de signal pour être fiable, jamais une erreur. Nécessite le Heurix Tracker pour un résultat pertinent sur un site à trafic élevé : sans identifiant visiteur, deux achats de clients différents survenus presque au même instant peuvent, rarement, être confondus avec un seul panier.
heurix-search.jsBarre de recherche prête à l'emploi
Pas envie de coder l'appel fetch, le rendu des résultats et la gestion des facettes vous-même ? Une bibliothèque JavaScript autonome (zéro dépendance) affiche une barre de recherche complète — saisie, résultats en direct, facettes cliquables, navigation clavier — connectée à votre catalogue en quelques lignes.
🚀 Téléchargez heurix-search.js — un seul fichier, à poser où vous voulez sur votre site.
🔑 Utilisez une clé publique (hxp_) — ce script tourne dans le navigateur du visiteur, où la clé est lisible par tous. Une clé serveur donnerait accès à votre facturation.
Intégration minimale
<div id="ma-recherche"></div>
<script src="heurix-search.js"></script>
<script>
Heurix.searchBox({
apiKey: "VOTRE_CLE_PUBLIQUE",
catalog: "moncatalogue",
containerId: "ma-recherche"
});
</script>
C'est suffisant pour une barre de recherche fonctionnelle — saisie avec anti-rebond intégré, résultats affichés dès 2 caractères, tolérance aux fautes de frappe (gérée côté moteur, rien à faire ici), secours automatique sur zéro résultat si votre catalogue a des produits featured.
Options de configuration
| Option | Type | Description |
|---|---|---|
apiKey, catalog, containerId | string | Seules options obligatoires. |
facets | string[] | Champs à proposer en filtres cliquables (ex. ["brand", "color"]). Absent par défaut — aucune facette affichée tant que vous ne les listez pas explicitement. |
accentColor | string | Une couleur d'accent (ex. "#2952E3") pour le focus et les filtres actifs — personnalisation minimale par design, pas une refonte CSS complète. |
placeholder | string | Texte du champ de recherche. Défaut : « Rechercher… ». |
minChars | number | Nombre de caractères avant de déclencher une recherche. Défaut : 2. |
debounceMs | number | Délai d'anti-rebond en millisecondes. Défaut : 200. |
limit | number | Nombre maximal de résultats affichés. Défaut : 8. |
renderItem | function(hit) | Personnalise le HTML de chaque résultat. Reçoit un hit complet (voir la référence de recherche) ; par défaut affiche nom, référence, prix et rupture de stock. |
resultHref | function(hit) → string | Si fourni, chaque résultat devient un lien <a> vers l'URL renvoyée (ex. la fiche produit), plutôt qu'un simple élément cliquable. |
onSelect | function(hit) | Appelé au clic ou à la validation clavier (Entrée) sur un résultat — utile si vous gérez la navigation vous-même plutôt que via resultHref. |
baseUrl | string | Défaut : https://api.heurix.fr. À ne changer que pour un environnement de test. |
Exemple complet, avec facettes et lien produit
Heurix.searchBox({
apiKey: "hxp_votre_cle_publique",
catalog: "moncatalogue",
containerId: "ma-recherche",
facets: ["brand"],
accentColor: "#C0392B",
resultHref: function (hit) {
return "/produits/" + hit.product.id;
}
});
Chaque recherche via ce widget consomme le quota normal de la clé utilisée, exactement comme un appel fetch direct au point d'entrée de recherche — ce n'est qu'une façade, pas un nouveau mécanisme de facturation.
Le style visuel fourni reste volontairement minimal — fonctionnel et lisible, pensé pour être facilement personnalisé (chaque élément a une classe CSS préfixée hx-) plutôt que pour correspondre à une charte graphique précise dès cette version.
Serveur Heurix pour agents IAInterroger Heurix depuis Claude Desktop, Cursor, ou un agent interne
Un serveur MCP (Model Context Protocol) qui expose la recherche et Browse comme des outils qu'un agent IA sait appeler nativement — un collaborateur peut demander « est-ce que j'ai des vis M8 en stock ? » en langage naturel, sans jamais toucher à l'API. Trois outils : heurix_search, heurix_browse, heurix_catalog_stats.
Prérequis : Python 3.10 ou plus, installé sur la machine où tourne l'agent (votre ordinateur, pas un serveur) — le serveur MCP se lance localement, à la demande, par Claude Desktop ou Cursor eux-mêmes.
🚀 Téléchargez le serveur MCP — installation et configuration détaillées (Claude Desktop et Cursor) sur le guide dédié.
pip install -r requirements.txt
HEURIX_API_KEY=hx_votre_cle python3 server.py
La clé API vit uniquement dans la configuration locale du client MCP (un fichier JSON sur la machine de l'utilisateur), jamais transmise en clair dans un appel d'outil. Chaque appel consomme le quota normal de la clé utilisée — heurix_search et heurix_browse comptent comme n'importe quel appel de recherche ou de Browse, heurix_catalog_stats non.
/healthSanté du service
Liveness, sans authentification — pratique pour vos sondes de supervision.
{"status": "ok", "catalogs": 3}
La cascade d'annotations
C'est le cœur du moteur. Un pack de règles est organisé en niveaux : le niveau 1 applique des expressions régulières sur le texte normalisé et produit des annotations ; les niveaux suivants s'appliquent sur le flux d'annotations et les composent. Documents et requêtes traversent la même cascade, la correspondance se fait donc dans un espace partagé :
« m8x20 inox » « M8 x 20 — A2 » (fiche produit)
│ │
▼ niveau 1 ▼ niveau 1
DIAM_M8, LONG_20, MAT_INOX DIAM_M8, LONG_20, MAT_INOX
│ │
▼ niveau 2 ▼ niveau 2
VIS_M8X20 ────────── correspondance ────── VIS_M8X20
Chaque annotation partagée pèse fortement dans le score — c'est ce qui fait passer la bonne référence en tête même quand la forme écrite diffère. Le champ matched de chaque résultat rend ces annotations visibles.
Bonnes pratiques
Remplissez ref, name et description distinctement. C'est la pondération entre ces trois champs qui fait la qualité du tri — tout concaténer dans name aplatit la pertinence.
Gardez les références telles quelles. N'essayez pas de « nettoyer » vos références produits avant indexation (retirer les espaces, les tirets...) : la normalisation et la cascade s'en chargent, et la forme d'origine reste disponible pour l'affichage.
Indexez par lots de 1 000 à 5 000. Un lot = un appel réseau ; trop petit multiplie les appels, la limite est à 5 000 par appel.
Envoyez le stock à chaque mise à jour. Le tri à pertinence égale repose dessus ; un stock à jour évite de mettre en avant des produits indisponibles.
Un catalogue par langue. Si votre boutique existe en français et en anglais, créez boutique-fr et boutique-en — les synonymes et les règles restent cohérents par langue.
Utilisez matched pour régler la pertinence. Chaque résultat explique pourquoi il sort : si un produit remonte à tort, ce champ montre quel terme ou quelle annotation l'a fait matcher — c'est votre outil de diagnostic.
Codes d'erreur
| Code | Signification | Que faire |
|---|---|---|
401 | En-tête Authorization absent ou mal formé | Envoyez Authorization: Bearer <clé> |
403 | Clé API invalide | Vérifiez la clé ; contactez-nous si elle a été révoquée |
404 | Catalogue ou produit introuvable | Vérifiez le nom du catalogue et l'id — le catalogue est créé au premier appel d'indexation, pas avant |
422 | Corps de requête invalide | Le détail de l'erreur indique le champ en cause (ex : produit sans id) |
5xx | Erreur côté serveur | Réessayez ; si l'erreur persiste, écrivez à contact@heurix.fr |
Limites
| Requête de recherche | 500 caractères maximum |
| Résultats par page | 100 maximum (limit) |
| Indexation | 5 000 produits par appel — envoyez plusieurs lots pour un catalogue plus grand |
| Groupes de synonymes | 2 000 par catalogue |
| CORS | Les appels navigateur ne sont pas ouverts : appelez l'API depuis votre serveur, pas depuis le JavaScript public (votre clé y serait exposée) |
Un besoin au-delà de ces limites ? Parlons-en — c'est le rôle du plan Scale et des configurations dédiées.