CODFamiliaAPI v1.3

Webhooks

Plutôt que d'interroger l'API en boucle pour savoir si une commande a bougé, laissez la plateforme appeler votre serveur au moment où elle bouge.

Enregistrer une adresse

Dans Applications → API, ajoutez l'adresse HTTPS de votre serveur et choisissez les événements qui vous intéressent. Un secret de signature vous est donné à ce moment-là, et une seule fois.

Enregistrer une adresse

Événements

lead.createdUn lead est entré (saisie, feuille, boutique ou API).
lead.confirmedUn agent a confirmé la commande avec le client.
lead.canceledLe lead est perdu (annulé, faux numéro, doublon, fantaisiste).
order.shippedLe colis est parti chez le livreur.
order.deliveredLe colis est livré et encaissé côté livreur.
order.returnedLe colis revient (refus ou client injoignable).
order.paidLa commande est payée au vendeur (écriture au grand livre).

Vous pouvez viser une famille entière : order.*. Sans précision, tous les événements sont envoyés.

Ce que vous recevez

Un POST en JSON, avec ces en-têtes :

X-CODFamilia-EventLe code de l'événement.
X-CODFamilia-DeliveryIdentifiant de l'envoi — le même en cas de réessai.
X-CODFamilia-TimestampHorodatage Unix de l'envoi.
X-CODFamilia-Signaturesha256=… (voir plus bas).
{
  "event": "order.delivered",
  "sent_at": "2026-05-04T11:22:33+01:00",
  "data": {
    "id": 412,
    "ref": "TAH-00042",
    "external_ref": "CMD-1042",
    "customer": { "name": "Yassine A.", "phone": "0612345678", "city": "Casablanca", "address": "12 rue des Orangers" },
    "total_client": "299.00",
    "seller_profit": "90.00",
    "confirmation_status": "confirmed",
    "shipping_status": "delivered",
    "payment_status": "unpaid",
    "tracking_number": "OZ123456",
    "items": [{ "sku": "CF-TEETH-03", "name": "Stylo blanchiment dentaire", "quantity": 1 }]
  }
}

Vérifier la signature

Une adresse « secrète » ne prouve rien : quiconque la découvre peut vous envoyer un faux « commande livrée ». Vérifiez donc la signature avant de traiter l'événement. Elle est calculée sur horodatage . "." . corps brut — le corps tel qu'il arrive, avant tout décodage.

<?php
$body = file_get_contents('php://input');
$ts   = $_SERVER['HTTP_X_CODFAMILIA_TIMESTAMP'] ?? '';
$sig  = $_SERVER['HTTP_X_CODFAMILIA_SIGNATURE'] ?? '';
$mine = 'sha256=' . hash_hmac('sha256', $ts . '.' . $body, 'whsec_votre_secret');

if (!hash_equals($mine, $sig) || abs(time() - (int) $ts) > 300) {
    http_response_code(400);              // signature invalide, ou envoi trop ancien (rejeu)
    exit;
}
$event = json_decode($body, true);
// … traitez $event['data'], puis répondez 200 le plus vite possible
http_response_code(200);
# Node.js
const crypto = require('crypto');
const mine = 'sha256=' + crypto.createHmac('sha256', SECRET).update(ts + '.' + rawBody).digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(mine), Buffer.from(sig))) return res.sendStatus(400);

Réessais

Un envoi est réussi si votre serveur répond un code 2xx. Sinon il est réessayé, de plus en plus espacé (1, 5, 25, 125 minutes, puis toutes les 4 heures), jusqu'à 6 tentatives. Un serveur éteint une nuit retrouve donc ses événements au matin ; un serveur définitivement disparu n'est pas appelé indéfiniment. Après 25 échecs consécutifs, l'adresse est désactivée et vous en êtes averti : vous la réactivez d'un clic une fois votre serveur réparé.

Répondez vite, traitez après. Le délai d'attente est de 10 secondes. Enregistrez l'événement et répondez 200 ; faites le travail ensuite, dans votre propre file. Un même événement peut arriver deux fois (un réessai après une réponse perdue) : utilisez X-CODFamilia-Delivery pour l'ignorer la seconde fois.

Ce que vous ne recevrez jamais

Un webhook ne transporte que ce que le vendeur voit déjà dans son espace. Ni prix d'achat, ni marge de la plateforme, ni identité des agents : ce n'est pas une porte de service vers des données internes.