Kayroo Connect
Tout ce qu'un développeur externe doit savoir pour lire les données d'une boutique et réagir à ses événements.
Sur cette page
Kayroo est une plateforme e-commerce (proche dans son fonctionnement de Shopify) qui permet à des marchands en Algérie de gérer une boutique en ligne — produits, commandes, livraison, paiement — sans écrire une ligne de code. « Kayroo Connect » est le nom donné à la couche d'intégration publique de la plateforme : une API REST et un système de webhooks qui permettent à une application externe de dialoguer avec la boutique d'un marchand depuis l'extérieur.
C'est le même modèle de confiance qu'une « app » Shopify ou un plugin WooCommerce hébergé sur son propre serveur : votre application vit entièrement sur votre propre infrastructure, dans votre propre dépôt de code. Elle ne reçoit jamais de copie du code source de Kayroo, jamais d'identifiants de base de données, jamais d'accès SSH ni au panneau d'administration. Chaque interaction passe par les deux canaux décrits sur cette page :
Il n'existe aujourd'hui ni marketplace d'applications, ni bouton OAuth « installer », ni compte développeur à créer chez Kayroo. C'est le propriétaire de la boutique (le marchand) qui accorde lui-même l'accès à votre application, directement depuis son panneau d'administration. Le déroulé est le suivant :
Une fois que vous avez un jeton fourni par un marchand, chaque requête fonctionne de la même façon : une requête HTTPS GET avec le jeton dans l'en-tête Authorization, adressée au domaine de la boutique de ce marchand, sous /api/v1.
curl "https://example-store.kayroo.app/api/v1/store" \
-H "Authorization: Bearer kt_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-H "Accept: application/json"
Une réponse réussie ressemble à ceci :
{
"data": {
"id": "9f2c1a...",
"name": "Example Store",
"subdomain": "example-store",
"custom_domain": null,
"currency": "DZD",
"language": "fr",
"delivery_fee": 400,
"api_version": "v1"
}
}
Chaque requête doit inclure le jeton comme Bearer token dans l'en-tête Authorization :
Authorization: Bearer kt_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXX
Un jeton peut éventuellement avoir une date d'expiration, définie par le marchand lors de sa création. Une fois expiré, révoqué ou supprimé, le jeton cesse de fonctionner immédiatement sur toutes les requêtes suivantes — il n'y a pas de période de grâce.
Un jeton manquant, mal formé, expiré ou révoqué reçoit toujours la même réponse :
HTTP/1.1 401 Unauthorized
{ "error": "Invalid or expired token." }
Un jeton n'a jamais plus de pouvoir que les scopes cochés par le marchand à sa création. Chaque endpoint de l'API exige exactement un scope — ne demandez que ce dont votre intégration a réellement besoin ; un marchand fera bien plus confiance à une intégration qui ne demande pas tout.
| Scope | Donne accès à |
|---|---|
store.read |
Informations de base sur la boutique (nom, devise, langue, frais de livraison) |
products.read |
Catalogue produits, y compris variantes et stock |
orders.read |
Commandes et leurs lignes, totaux, et destination de livraison |
customers.read |
Comptes de segments clients et paniers abandonnés |
Si un jeton est utilisé pour appeler un endpoint pour lequel il n'a pas le scope requis, l'API répond :
HTTP/1.1 403 Forbidden
{
"error": "insufficient_scope",
"message": "This token is not authorized for the \"products.read\" scope.",
"required_ability": "products.read"
}
Tous les endpoints sont en lecture seule (GET) et se trouvent sous /api/v1. Toutes les réponses sont en JSON. Tous les montants sont des nombres en dinar algérien (DZD), sans conversion de devise.
Informations de base sur la boutique : nom, sous-domaine, domaine personnalisé (le cas échéant), devise, langue de la boutique, et frais de livraison fixes.
curl "https://example-store.kayroo.app/api/v1/store" \
-H "Authorization: Bearer kt_live_XXXX"
Une liste paginée des produits de la boutique. Paramètres de requête (tous optionnels) :
| Paramètre | Signification |
|---|---|
visible_only=1 |
Uniquement les produits actuellement affichés sur la boutique |
featured=1 |
Uniquement les produits mis en avant |
search=term |
Recherche sur le nom du produit ou le SKU |
per_page=25 |
Éléments par page (25 par défaut, 100 maximum) |
{
"data": [
{
"id": 41,
"name": "Classic Leather Wallet",
"slug": "classic-leather-wallet",
"sku": "WAL-041",
"description": "Full-grain leather, hand-stitched.",
"price": 3500,
"compare_price": 4200,
"current_price": 3500,
"on_sale": false,
"currency": "DZD",
"stock": 18,
"in_stock": true,
"is_visible": true,
"is_featured": true,
"category": "Accessories",
"image_url": "https://example-store.kayroo.app/storage/products/41.jpg",
"variants": [
{ "id": 101, "options": { "Color": "Brown" }, "price": null, "stock": 10 },
{ "id": 102, "options": { "Color": "Black" }, "price": null, "stock": 8 }
],
"created_at": "2026-02-11T09:12:00+00:00",
"updated_at": "2026-05-03T14:40:00+00:00"
}
],
"links": { "first": "...", "last": "...", "prev": null, "next": "..." },
"meta": { "current_page": 1, "last_page": 4, "per_page": 25, "total": 87 }
}
GET /api/v1/products/{id} renvoie le même format pour un produit unique (un objet simple sous « data »), ou un corps JSON 404 si l'ID n'existe pas sur cette boutique.
Une liste paginée des commandes. Paramètres de requête (tous optionnels) :
| Paramètre | Signification |
|---|---|
status=confirmed |
Une valeur parmi : pending, confirmed, delivered, cancelled |
since=2026-06-01 |
Uniquement les commandes créées à partir de cette date |
per_page=25 |
Éléments par page (25 par défaut, 100 maximum) |
{
"data": [
{
"id": 1032,
"status": "confirmed",
"customer": {
"name": "Amine K.",
"phone": "0555xxxxxx",
"email": null,
"address": "Cité 100 logements, Bt 4"
},
"items": [
{ "product_id": 41, "variant_id": 101, "name": "Classic Leather Wallet", "qty": 2, "line_total": 7000 }
],
"subtotal": 7000,
"discount_amount": 0,
"coupon_code": null,
"delivery_price": 400,
"total": 7400,
"currency": "DZD",
"wilaya": "Alger",
"commune": "Bab Ezzouar",
"tracking_number": "YAL-88213",
"landing_page_id": null,
"created_at": "2026-06-30T10:02:00+00:00",
"updated_at": "2026-07-01T08:15:00+00:00"
}
],
"links": { "...": "..." },
"meta": { "...": "..." }
}
Des comptes agrégés de clients regroupés en segments comportementaux — nouveaux, récurrents, champions (fréquents et à forte valeur), et à risque (clients qui achetaient mais plus récemment). Paramètre de requête optionnel : lookback_days (90 par défaut, entre 7 et 365).
{
"data": {
"new": 128,
"repeat": 54,
"champions": 12,
"at_risk": 31
},
"meta": { "lookback_days": 90 }
}
Une liste paginée des paniers que des clients ont commencés sans finaliser — utile pour des relances de récupération de panier. Paramètres de requête (tous optionnels) :
| Paramètre | Signification |
|---|---|
days=30 |
Uniquement les paniers commencés au cours des N derniers jours (30 par défaut, 365 max) |
include_recovered=1 |
Inclure ceux ayant ensuite abouti à une commande (exclus par défaut) |
{
"data": [
{
"id": 77,
"customer_name": "Yasmine B.",
"customer_phone": "0661xxxxxx",
"customer_email": null,
"cart": { "items": [ { "product_id": 41, "qty": 1 } ] },
"recovered": false,
"created_at": "2026-07-02T19:40:00+00:00"
}
]
}
Les endpoints de type liste (produits, commandes, paniers abandonnés) sont paginés. Chaque réponse de liste comporte trois clés de premier niveau : data (le tableau d'enregistrements de cette page), links (URLs first/last/prev/next) et meta (current_page, last_page, per_page, total). Passez ?page=2 pour la page suivante, ou ?per_page=100 pour la taille de page maximale.
Chaque jeton est limité par défaut à 120 requêtes par minute. Au-delà, vous recevrez une réponse HTTP 429 — ralentissez et réessayez après un court délai. Mettez en place une logique de nouvelle tentative avec backoff plutôt que de marteler l'API en boucle serrée ; cela protège aussi votre intégration d'être confondue avec un trafic abusif.
Les erreurs sont toujours du JSON brut avec une clé « error », et parfois un « message » lisible. Voici les codes de statut que vous rencontrerez :
| Statut | Signification | Cause typique |
|---|---|---|
401 |
Unauthenticated | Jeton manquant, invalide, expiré, ou révoqué |
403 |
insufficient_scope | Le jeton n'a pas le scope requis par l'endpoint |
404 |
not_found | L'ID de l'enregistrement n'existe pas sur cette boutique |
422 |
Erreur de validation | Un paramètre de requête avait une valeur invalide |
429 |
Too many requests | Limite de débit dépassée — ralentissez et réessayez |
Plutôt que d'interroger l'API en continu pour savoir « est-ce que quelque chose a changé ? », vous pouvez demander à Kayroo de notifier votre serveur dès qu'un événement se produit. Le marchand enregistre l'URL de votre endpoint depuis Paramètres → Webhooks dans son panneau d'administration et choisit parmi les événements suivants lesquels vous envoyer :
| Événement | Se déclenche quand… |
|---|---|
order.created |
Une nouvelle commande est passée (depuis le paiement, ou créée manuellement par le marchand) |
order.updated |
Le statut d'une commande change (ex. pending → confirmed → delivered) |
order.cancelled |
Une commande est annulée |
product.created |
Un nouveau produit est ajouté au catalogue |
product.updated |
Un produit est modifié (prix, stock, détails, …) |
product.deleted |
Un produit est retiré du catalogue |
lead.created |
Un visiteur soumet le formulaire de contact de la boutique |
review.created |
Un acheteur vérifié soumet un avis produit |
Chaque webhook est une requête HTTP POST vers l'URL enregistrée par le marchand, avec ce format de corps JSON :
{
"event": "order.created",
"data": {
"id": 1032,
"status": "pending",
"total": 7400,
"customer_name": "Amine K.",
"customer_phone": "0555xxxxxx",
"created_at": "2026-06-30T10:02:00+00:00"
},
"timestamp": "2026-06-30T10:02:01+00:00"
}
La requête transporte aussi deux en-têtes sur lesquels vous pouvez vous appuyer :
| En-tête | Rôle |
|---|---|
X-Webhook-Event |
Le nom de l'événement, identique au champ « event » du corps (ex. order.created) |
X-Webhook-Signature |
Une signature HMAC-SHA256 du corps brut de la requête — voir la vérification ci-dessous |
Avant de faire confiance à un webhook, vérifiez sa signature. Chaque abonnement webhook possède son propre secret, généré par Kayroo lorsque le marchand enregistre votre endpoint, et affiché une seule fois au marchand pour qu'il vous le transmette de façon sécurisée. Pour vérifier une requête :
Exemple de vérification en PHP :
$rawBody = file_get_contents('php://input');
$expected = hash_hmac('sha256', $rawBody, $sharedSecret);
$received = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
if (! hash_equals($expected, $received)) {
http_response_code(401);
exit;
}
// Signature vérifiée — vous pouvez traiter $rawBody en toute sécurité.
Exemple de vérification en Node.js :
const crypto = require('crypto');
function isValidSignature(rawBody, signatureHeader, sharedSecret) {
const expected = crypto
.createHmac('sha256', sharedSecret)
.update(rawBody)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signatureHeader || '')
);
}
L'accès API et les webhooks sont disponibles pour les marchands sur le forfait Scale de Kayroo et sur le forfait à la consommation (Pay-As-You-Go). Si un marchand avec qui vous vous intégrez ne trouve pas Paramètres → Jetons API dans son panneau d'administration, c'est généralement la raison — demandez-lui de vérifier son forfait actuel.
Cette API continuera d'évoluer. Si votre intégration a besoin d'une donnée ou d'un événement qui n'est pas couvert ici, ne cherchez pas de contournement via un accès direct — demandez au marchand de transmettre votre demande à l'équipe Kayroo, ou contactez-nous directement à [email protected].