Skip to content

Suivi de commande ​

Page Agent IA → Compétences → Suivi de commande dans le dashboard (app.thehumind.com).

L'agent support sait répondre seul à « où en est ma commande ? ». Le visiteur donne un numéro de commande et l'email utilisé lors de l'achat, l'agent retrouve la commande, et le chat affiche une carte avec le statut de préparation, le lien de suivi transporteur, la chronologie de livraison et les articles. L'agent la résume ensuite dans la conversation.

Rien à écrire de votre côté si vous êtes sur Shopify. Tous les autres (PrestaShop, WooCommerce, Magento, OMS ou ERP maison) exposent un seul endpoint HTTPS que Humind appelle au moment de la recherche. Cette page documente cet endpoint.

Quelle intégration s'applique ​

Votre stackQuoi faire
Shopify (app Humind installée)Rien. Les commandes sont lues en direct dans votre boutique via l'Admin API. La page Compétences affiche « Connecté via Shopify ».
Toute autre plateformeExposez l'endpoint décrit ci-dessous et enregistrez-le dans Agent IA → Compétences → Suivi de commande → API personnalisée.

Quelques règles :

  • L'outil s'active tout seul dès qu'une intégration est détectée. Vous pouvez le désactiver depuis la page Compétences, comme n'importe quelle autre compétence.
  • Si une API personnalisée est activée et qu'une boutique Shopify est connectée, l'API personnalisée l'emporte.
  • Humind ne synchronise pas votre base de commandes. Chaque recherche est un appel en direct à votre endpoint, et seuls les champs listés dans le contrat arrivent dans la conversation. La commande affichée au visiteur est conservée dans l'historique de la conversation, comme le reste du fil, et visible dans votre inbox.

Comment se déroule une recherche ​

  1. Le visiteur pose une question sur une commande. S'il manque le numéro de commande ou l'email, le chat affiche un petit formulaire qui demande les deux.
  2. Humind envoie un POST à votre endpoint avec le couple { orderNumber, email }.
  3. Votre endpoint répond { "found": false } ou { "found": true, "order": { ... } }.
  4. Humind valide la réponse, supprime les champs inconnus et affiche la carte.

Garde-fous côté Humind, pour savoir à quoi vous attendre :

RègleValeur
Délai maximal8 secondes. Répondez vite, depuis votre base de données, pas depuis une API transporteur appelée de façon synchrone.
RedirectionsRefusées. Une redirection ferait fuiter votre secret vers un autre hôte. Répondez sur l'URL que vous avez enregistrée.
Recherches en échec5 par conversation, ensuite l'agent arrête d'essayer. Un found: false compte comme un échec. Une erreur technique (statut autre que 200, délai dépassé, réponse invalide) ne compte pas, et votre endpoint peut être appelé jusqu'à 3 fois au total par tentative (2 relances) : gardez l'endpoint idempotent et appliquez votre propre limite de débit si besoin.
HTTPSObligatoire. Les URL en HTTP sont refusées à l'enregistrement de la configuration.

Configuration dans le dashboard ​

Ouvrez Agent IA → Compétences, cliquez sur Suivi de commande, puis remplissez la section API personnalisée :

  • URL de l'endpoint (HTTPS) : l'URL que Humind appellera.
  • Authentification : Aucune, Bearer token (envoyé en Authorization: Bearer <secret>) ou Clé API (header) (envoyée dans le header dont vous choisissez le nom, X-Api-Key par défaut).
  • Secret : écrit une fois, jamais réaffiché. Laissez-le vide lors des enregistrements suivants pour conserver le secret actuel.
  • Utiliser cette API pour le suivi de commande : l'interrupteur qui active l'intégration.

Cliquez sur Enregistrer, puis utilisez la section Tester. Elle apparaît une fois une configuration enregistrée et s'exécute toujours sur la configuration enregistrée, même si l'interrupteur est coupé. Saisissez un vrai numéro de commande et son email d'achat, puis cliquez sur Tester : le test effectue une vraie recherche et affiche soit la commande trouvée, soit « aucune commande ne correspond » (votre endpoint a correctement répondu found: false), soit le message d'erreur.

Contrat de l'endpoint ​

Requête ​

http
POST https://www.example.com/humind/track-order
Content-Type: application/json
Authorization: Bearer <secret>

{ "orderNumber": "1042", "email": "jane@example.com" }

orderNumber est ce que le visiteur a tapé, sans espaces autour mais sans autre normalisation, de 1 à 64 caractères. Il peut porter ou non un préfixe # et être dans n'importe quelle casse : normalisez-le de votre côté (retirer le #, mettre en majuscules, supprimer les espaces) avant de chercher. email arrive sans espaces et en minuscules ; comparez-le quand même sans tenir compte de la casse de votre côté.

Réponse quand la commande n'est pas trouvée, ou que l'email ne correspond pas ​

json
{ "found": false }

Répondez toujours 200 avec found: false dans ce cas. Ne répondez pas 404 ni 403 : tout statut autre que 200 est traité comme une panne technique et le visiteur apprend que la recherche est indisponible, ce qui est une moins bonne expérience que « aucune commande ne correspond à ces informations ».

Réponse quand la commande est trouvée ​

json
{
  "found": true,
  "order": {
    "orderNumber": "1042",
    "createdAt": "2026-06-01T10:00:00Z",
    "fulfillmentStatus": "fulfilled",
    "financialStatus": "paid",
    "shipmentStatus": "out_for_delivery",
    "estimatedDeliveryAt": "2026-06-04T00:00:00Z",
    "statusPageUrl": "https://www.example.com/account/orders/1042",
    "deliveryMethod": "shipping",
    "trackingInfo": [
      { "company": "Colissimo", "number": "6A12345678901", "url": "https://www.laposte.fr/outils/suivre-vos-envois?code=6A12345678901" }
    ],
    "destination": { "address1": "12 rue de la Paix", "zip": "69001", "city": "Lyon", "country": "France" },
    "lineItems": [
      { "title": "Huile CBD 10%", "quantity": 1, "imageUrl": "https://www.example.com/img/huile-10.jpg" }
    ],
    "events": [
      { "status": "order_placed", "happenedAt": "2026-06-01T10:00:00Z" },
      { "status": "fulfilled", "happenedAt": "2026-06-02T08:00:00Z" },
      { "status": "in_transit", "happenedAt": "2026-06-03T06:30:00Z", "message": "Departed facility", "location": "Lyon, France" }
    ]
  }
}

Seuls orderNumber, createdAt et fulfillmentStatus sont obligatoires. Un endpoint minimal qui ne renvoie que ces trois champs donne déjà une réponse utile au visiteur.

Champs ​

ChampObligatoireTypeNotes
orderNumberouichaîne, 1 à 64Le numéro tel que le client le connaît.
createdAtouidate ISO 8601Date de la commande.
fulfillmentStatusouichaîne, 64 maxTraduit dans la langue du visiteur quand c'est une clé connue : unfulfilled, partially_fulfilled, fulfilled, delivered, ready_for_pickup, picked_up, voided. Toute autre valeur est affichée humanisée dans la langue où vous l'avez écrite (shipped s'affiche « Shipped » à un visiteur français), donc préférez les clés connues.
financialStatusnonchaîne, 64 maxClés traduites : pending, authorized, paid, partially_paid, refunded, partially_refunded, voided. Toute autre valeur est affichée humanisée.
shipmentStatusnonchaîne, 64 maxStatut d'expédition plus fin quand vous l'avez. Quand il est présent, il devient le badge principal de la carte. Clés traduites : in_transit, out_for_delivery, delivered, ready_for_pickup, picked_up. Toute autre valeur est affichée humanisée.
estimatedDeliveryAtnondate ISO 8601Estimation de livraison, affichée sur la carte.
statusPageUrlnonURL, 2048 maxUne page de votre site où le client voit la commande complète. Ne doit pas exiger des identifiants que le visiteur n'a pas.
deliveryMethodnonshipping, pickup, localshipping par défaut. pickup bascule la carte sur sa mise en page click-and-collect et affiche pickupLocation à la place de destination.
pickupLocationnon{ name, address }Le magasin ou point relais, pour les commandes en retrait. Votre adresse, pas celle du client. name 160 max, address 256 max.
trackingInfonontableau, 20 maxUne entrée par colis : company (nom du transporteur), number, url (la page de suivi du transporteur). Chaînes de 128 caractères max, url 2048 max.
destinationnon{ address1, zip, city, country }Où va le colis. Rue et code postal sont autorisés parce que le visiteur a prouvé qu'il possède la commande avec l'email. Ne renvoyez jamais le nom ni le téléphone du destinataire. address1 160 max, zip 32 max, city et country 128 max.
lineItemsnontableau, 50 maxtitle (obligatoire, 256 max), quantity (entier de 1 à 10000, 1 par défaut), imageUrl (optionnel, 2048 max).
eventsnontableau, 20 max, chronologiqueLe parcours du colis. Chaque étape a status (obligatoire, 64 max), happenedAt (obligatoire, ISO 8601), et en option message (256 max) et location (160 max). En son absence, Humind ajoute une seule étape order_placed datée de createdAt. La chronologie s'affiche à partir de deux étapes.

events[].status est une clé en minuscules. Les clés connues sont traduites dans la langue du visiteur : order_placed, confirmed, label_purchased, label_printed, fulfilled, ready_for_pickup, carrier_picked_up, picked_up, in_transit, out_for_delivery, attempted_delivery, delayed, failure, delivered. Toute autre clé est affichée humanisée (left_warehouse devient « Left warehouse »).

Les champs inconnus sont ignorés. Un champ plus long que sa limite, un tableau plus long que son maximum, ou un null dans un champ optionnel rend toute la réponse invalide : le visiteur voit « recherche indisponible » et le panneau de test affiche « response does not match the expected contract » sans plus de détail. Omettez un champ optionnel que vous n'avez pas plutôt que d'envoyer null, et tronquez de votre côté plutôt que d'envoyer tout ce que vous avez.

Liste de contrôle sécurité ​

  • Faites correspondre les deux identifiants. Ne renvoyez la commande que lorsque le numéro de commande et l'email appartiennent à la même commande. C'est votre moitié de la vérification : Humind ne peut pas la faire à votre place. Quelqu'un qui connaît un numéro de commande mais pas l'email doit obtenir found: false.
  • Protégez l'endpoint avec un bearer token ou un en-tête de clé API et refusez les requêtes qui n'en ont pas. Le secret est stocké chiffré chez Humind et n'est envoyé qu'à l'URL exacte que vous avez enregistrée.
  • Aucune donnée personnelle au-delà du contrat. Pas de nom de destinataire, pas de téléphone, pas de données de paiement. Rue, code postal et ville suffisent à rassurer un client sur la destination.
  • Limitez le débit de l'endpoint si vous le souhaitez. Humind s'arrête après 5 réponses found: false par conversation, et chaque recherche est déclenchée par un visiteur qui a saisi les deux identifiants, mais les erreurs techniques sont retentées et non plafonnées.

Exemple : PrestaShop ​

Sur PrestaShop, le client connaît la référence de commande (XKBKNABJK), donc cherchez par référence, pas par id_order. Un contrôleur front de module minimal ressemble à ceci. C'est un point de départ à adapter, pas un module prêt à l'emploi.

php
<?php
// modules/humindtracking/controllers/front/track.php
class HumindTrackingTrackModuleFrontController extends ModuleFrontController
{
    public function postProcess()
    {
        header('Content-Type: application/json');

        // Configured as "API key (header)" in the Humind dashboard, header name X-Api-Key.
        // Some Apache setups strip the Authorization header, so an API key header is the safer choice on PrestaShop.
        $secret = (string) Configuration::get('HUMIND_TRACKING_SECRET');
        $given = (string) ($_SERVER['HTTP_X_API_KEY'] ?? '');
        if ($secret === '' || !hash_equals($secret, $given)) {
            http_response_code(401);
            exit(json_encode(['error' => 'unauthorized']));
        }

        $input = json_decode((string) file_get_contents('php://input'), true) ?: [];
        $reference = strtoupper(trim(ltrim((string) ($input['orderNumber'] ?? ''), '#')));
        $email = strtolower(trim((string) ($input['email'] ?? '')));
        if ($reference === '' || $email === '') {
            exit(json_encode(['found' => false]));
        }

        // An order split into several shipments shares one reference: this example keeps the first one only.
        $orders = Order::getByReference($reference);
        $order = $orders->count() ? $orders->getFirst() : null;
        if (!$order) {
            exit(json_encode(['found' => false]));
        }
        $customer = new Customer((int) $order->id_customer);
        if (strtolower((string) $customer->email) !== $email) {
            exit(json_encode(['found' => false])); // same answer as "not found": never reveal that the reference exists
        }

        $carrier = new Carrier((int) $order->id_carrier);
        // The tracking number lives on order_carrier (Order::$shipping_number was removed in PrestaShop 8).
        $orderCarrier = new OrderCarrier((int) $order->getIdOrderCarrier());
        $trackingNumber = (string) $orderCarrier->tracking_number;

        $payload = [
            'orderNumber' => (string) $order->reference,
            'createdAt' => date('c', strtotime($order->date_add)),
            // Map your states to the keys the chat translates; $state->name would be shown untranslated to every visitor.
            'fulfillmentStatus' => $order->hasBeenDelivered() ? 'delivered' : ($order->hasBeenShipped() ? 'fulfilled' : 'unfulfilled'),
            'financialStatus' => $order->hasBeenPaid() ? 'paid' : 'pending',
        ];

        // Only set optional keys when you have a value: a JSON null fails validation on the Humind side.
        if ($order->hasBeenDelivered()) {
            $payload['shipmentStatus'] = 'delivered';
        } elseif ($order->hasBeenShipped()) {
            $payload['shipmentStatus'] = 'in_transit';
        }
        if ($trackingNumber !== '') {
            $payload['trackingInfo'] = [[
                'company' => (string) $carrier->name,
                'number' => $trackingNumber,
                'url' => $carrier->url ? str_replace('@', $trackingNumber, (string) $carrier->url) : '',
            ]];
        }

        $items = [];
        foreach ($order->getProducts() as $product) {
            $items[] = ['title' => (string) $product['product_name'], 'quantity' => max(1, (int) $product['product_quantity'])];
        }
        $payload['lineItems'] = array_slice($items, 0, 50);

        exit(json_encode(['found' => true, 'order' => $payload]));
    }
}

Enregistrez l'URL (https://www.example.com/module/humindtracking/track) dans le dashboard avec l'authentification Clé API (header), nom du header X-Api-Key, et lancez le test avec une vraie commande.

La même logique s'applique à WooCommerce (une route REST sous humind/v1, recherche par numéro de commande et comparaison avec billing_email) ou à n'importe quel back-office maison.

Testez vous-même ​

Avant de configurer le dashboard, appelez votre endpoint comme Humind le fait :

bash
curl -sS -X POST https://www.example.com/module/humindtracking/track \
  -H 'Content-Type: application/json' \
  -H 'X-Api-Key: <secret>' \
  -d '{"orderNumber":"XKBKNABJK","email":"jane@example.com"}'

Vérifiez trois cas : un couple valide renvoie la commande, une référence valide avec un mauvais email renvoie { "found": false }, et une clé API absente ou fausse renvoie 401.

Dépannage ​

Symptôme dans le panneau de testCause
« Custom tracking API is unreachable »DNS, pare-feu, erreur TLS, l'endpoint a mis plus de 8 secondes, ou l'URL redirige (module désactivé, http vers https, www).
« Custom tracking API returned HTTP 401 » (ou tout statut autre que 200)Authentification incorrecte, ou votre endpoint répond un statut d'erreur au lieu de found: false.
« Custom tracking API returned invalid JSON »Le corps de la réponse n'est pas du JSON (page d'erreur HTML, avertissement PHP imprimé avant le JSON).
« response does not match the expected contract »Un champ obligatoire manque, une valeur est trop longue, un champ optionnel est à null, ou quantity vaut 0. Le panneau n'affiche que ce message générique : vérifiez le tableau des champs.
« Aucune commande ne correspond » alors que la commande existeNormalisation de la référence (#, casse) ou comparaison de l'email de votre côté.

Released under the proprietary Humind license.