L'API Commerce permet à n'importe quelle boutique d'envoyer ses événements vers Kanal : commandes, paniers abandonnés, clients et expéditions. Ces données alimentent ensuite vos automatisations WhatsApp, sans passer par Shopify.
Contrairement à l'API Messaging, elle ne nécessite pas d'abonnement actif. La référence complète est sur developers.getkanal.com.
Vous n'avez pas à savoir si un enregistrement existe déjà dans Kanal. Vous envoyez l'objet complet, et Kanal le crée ou le met à jour. Chaque ressource est identifiée par le couple (store_id, external_id).
external_id est votre identifiant : numéro de commande, jeton de panier, identifiant client. Renvoyez le même external_id et Kanal met à jour l'enregistrement existant au lieu de créer un doublon.
201 Created : Kanal voyait cet external_id pour la première fois.
200 OK : un enregistrement existant a été mis à jour.
Les deux retournent le même corps JSON : vous pouvez les traiter de la même manière.
POST rejoué sur une commande ou un panier peut redéclencher les automatisations attachées à cette ressource.POST /api/v1/stores/{store_id}/ordersDéclenche vos automatisations post-achat. Champs requis : external_id, placed_at (format ISO 8601), total_price et l'objet customer contenant au minimum phone.
Champs optionnels : currency, financial_status, fulfillment_status, line_items, tags, metadata. L'objet client accepte aussi external_id, first_name, last_name, email, locale, tags, lifetime_value et orders_count.
curl -X POST https://api.getkanal.com/api/v1/stores/123/orders \
-H "Authorization: Bearer VOTRE_CLE_API" \
-H "Content-Type: application/json" \
-d '{
"external_id": "ORDER-1001",
"placed_at": "2026-05-18T10:00:00Z",
"total_price": 49.90,
"currency": "EUR",
"customer": { "phone": "+33612345678", "first_name": "Marie" }
}'Pour ne modifier que le statut d'une commande existante, utilisez PATCH /orders/{external_id}. Seuls financial_status, fulfillment_status, tags et metadata sont modifiables. Une commande inexistante retourne une erreur 404.
curl -X PATCH https://api.getkanal.com/api/v1/stores/123/orders/ORDER-1001 \
-H "Authorization: Bearer VOTRE_CLE_API" \
-H "Content-Type: application/json" \
-d '{ "financial_status": "paid" }'POST /api/v1/stores/{store_id}/checkoutsAlimente vos automatisations de récupération de panier. Champs requis : external_id, abandoned_at, total_price et l'objet customer avec son phone.
Le champ recovery_url est optionnel mais fortement recommandé : c'est le lien que le client suivra pour reprendre sa commande, celui que vous placerez dans votre template de relance.
curl -X POST https://api.getkanal.com/api/v1/stores/123/checkouts \
-H "Authorization: Bearer VOTRE_CLE_API" \
-H "Content-Type: application/json" \
-d '{
"external_id": "CHECKOUT-7700",
"abandoned_at": "2026-05-18T09:40:00Z",
"recovery_url": "https://shop.example.com/checkout/recover/7700",
"total_price": 49.90,
"currency": "EUR",
"customer": { "phone": "+33612345678", "first_name": "Marie" }
}'Le PATCH /checkouts/{external_id} permet de faire évoluer le statut du panier, avec les valeurs active, abandoned, recovered, completed ou expired. Pensez à passer un panier en recovered dès qu'il est converti, pour éviter des relances inutiles.
POST /api/v1/stores/{store_id}/customersSynchronise les profils clients, leurs tags et leur valeur vie. Seul phone est requis. La clé naturelle est external_id, mais si vous l'omettez, c'est le phone qui sert de clé.
curl -X POST https://api.getkanal.com/api/v1/stores/123/customers \
-H "Authorization: Bearer VOTRE_CLE_API" \
-H "Content-Type: application/json" \
-d '{
"external_id": "CUST-42",
"phone": "+33612345678",
"first_name": "Marie",
"tags": ["vip"],
"lifetime_value": 1299,
"orders_count": 7
}'Pour honorer une demande d'effacement RGPD venant de votre boutique, utilisez DELETE /customers/{external_id}. La réponse est un 204 sans corps. L'appel est idempotent : supprimer un client déjà supprimé ou inconnu retourne également 204.
POST /api/v1/stores/{store_id}/shipmentsDéclenche vos notifications de livraison. Champs requis : external_id et order_external_id, qui rattache l'expédition à la commande correspondante.
Champs optionnels : tracking_number, tracking_url, carrier, metadata, et status parmi pending, in_transit, delivered, failed ou returned.
curl -X POST https://api.getkanal.com/api/v1/stores/123/shipments \
-H "Authorization: Bearer VOTRE_CLE_API" \
-H "Content-Type: application/json" \
-d '{
"external_id": "SHIP-9001",
"order_external_id": "ORDER-1001",
"tracking_number": "1Z999AA10123456784",
"tracking_url": "https://track.example.com/1Z999AA10123456784",
"carrier": "Colissimo",
"status": "in_transit"
}'Il n'existe pas de PATCH pour les expéditions : renvoyez un POST avec le même external_id pour mettre à jour le suivi ou le statut.
L'API Commerce est limitée à 500 requêtes par minute et par boutique. Ce budget est partagé entre tous les endpoints d'une même boutique. En cas de dépassement, l'API retourne un 429 accompagné d'un en-tête Retry-After. Des en-têtes X-RateLimit-* sont présents sur chaque réponse pour suivre votre consommation.
Trois principes pour rester sous la limite : envoyez un upsert complet plutôt que plusieurs PATCH partiels, poussez vos données au moment où elles changent au lieu d'interroger l'API en boucle, et appliquez un backoff exponentiel sur les 429. Si vous prévoyez un volume soutenu supérieur à 500 requêtes par minute, par exemple un import historique ou une vente flash, prévenez votre contact Kanal en amont pour faire relever la limite.
Les erreurs prennent deux formes. Les problèmes détectés avant validation (clé, boutique, limite) retournent une simple chaîne error. Les payloads invalides retournent un 422 avec un message et une carte errors détaillée par champ, en notation pointée pour les objets imbriqués.
{
"message": "The customer.phone field is required.",
"errors": {
"customer.phone": ["The customer.phone field is required."]
}
}Code | Signification | Rejouer ? |
|---|---|---|
| Mise à jour ou création réussie | — |
| Suppression effectuée, sans corps | — |
| Paramètre store_id manquant dans l'URL | Non |
| Clé absente, invalide ou non autorisée | Non |
| Boutique inconnue ou en pause, ou enregistrement introuvable | Non |
| Validation échouée : corrigez le payload | Non |
| Limite de débit dépassée | Oui, après Retry-After |
| Erreur serveur passagère | Oui, avec backoff exponentiel |