FREDFRED docs

Webhooks FRED : recevoir les événements et le suivi colis

Configurer, sécuriser et superviser les notifications de votre application.

Publié par FRED

Créer une intégration

curl -X POST https://api.fredpod.com/v1/webhook_endpoints \
  -H "X-API-Key: VOTRE_CLE" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: creation-boutique-001" \
  -d '{"description":"Ma boutique","url":"https://votre-app.fr/webhooks/fred","events":["order.*","shipment.*"]}'

Le scope webhooks:manage est requis. L’URL doit utiliser HTTPS, un port 80 ou 443 et une destination publique, sans identifiants ni fragment. Les adresses privées, locales et les redirections sont refusées ; la résolution DNS est vérifiée et fixée à chaque livraison pour limiter les attaques SSRF.

La réponse de création contient le secret whsec_…. Enregistrez-le dans votre gestionnaire de secrets : il n’apparaît pas dans les listes. Une répétition de la même création avec la même clé d’idempotence permet de récupérer sa réponse. Les secrets et ces réponses mémorisées sont chiffrés en base, et les réponses HTTP de gestion portent Cache-Control: no-store.

GET /v1/webhook_endpoints/event-types fournit le catalogue des événements et des familles. Utilisez des types précis, une famille comme order.*, ou * seul. Les listes vides et les types inconnus sont refusés.

Test et production

Une clé sk_test_… opère dans le bac à sable ; elle ne peut pas accéder à la production. Depuis une session vendeur, les pages et routes de gestion acceptent ?mode=test pour gérer ce même environnement. Une clé de production peut aussi sélectionner son bac à sable avec ce paramètre.

Les notifications du bac à sable sont réellement envoyées à l’URL configurée, avec des données de test. Elles ne créent aucun débit réel.

Mettre à jour la commande de votre client

Abonnez-vous à order.* et shipment.*. Les événements utilisent une enveloppe contenant id, type et data.object.

ÉvénementAction côté boutique
order.in_productionAfficher « En fabrication »
order.shippedAfficher « Expédiée » et relire les colis
order.deliveredAfficher « Livrée »
shipment.createdEnregistrer le transport et le suivi ; l’étiquette existe, le colis n’est pas forcément parti
shipment.updatedActualiser le statut et le lien de suivi du colis
shipment.deliveredEnregistrer la livraison signalée

Les événements de commande ont l’identifiant dans data.object.id. Les événements d’expédition portent data.object.order_id, data.object.tracking_number et data.object.tracking_url. Relisez GET /v1/storefront/orders/{order_id} pour récupérer l’état courant et la liste des colis. Les événements n’arrivent pas nécessairement dans l’ordre.

FRED transmet le suivi des colis à votre application. Les étiquettes d’expédition et les fichiers de fabrication sont gérés depuis l’atelier.

Pour vérifier votre réception, appelez POST /v1/webhook_endpoints/{endpoint_id}/test. Le 202 signifie que l’événement webhook.test est en file ; il ne crée ni commande ni paiement. Les livraisons, échecs, reprises et rotations de secret se gèrent dans Développeurs → Webhooks du dashboard.

Vérifier les signatures

Les nouveaux endpoints utilisent Standard Webhooks : retirez le préfixe whsec_, décodez le secret en base64, puis calculez HMAC-SHA256 sur les octets webhook-id.webhook-timestamp.corps_brut. Le corps ne doit pas être reparsé puis sérialisé avant vérification.

import base64
import hashlib
import hmac
import time


def verifier(secret: str, headers: dict, body: bytes) -> bool:
    try:
        msg_id = headers["webhook-id"]
        timestamp = headers["webhook-timestamp"]
        if not timestamp.isdigit() or abs(time.time() - int(timestamp)) > 300:
            return False
        key = base64.b64decode(secret.removeprefix("whsec_"), validate=True)
        message = f"{msg_id}.{timestamp}.".encode() + body
        expected = base64.b64encode(hmac.new(key, message, hashlib.sha256).digest()).decode()
        return any(
            hmac.compare_digest(part[3:], expected)
            for part in headers["webhook-signature"].split()
            if part.startswith("v1,")
        )
    except (KeyError, ValueError, TypeError):
        return False

Conservez une tolérance d’horloge courte (cinq minutes ici) et dédupliquez les événements par webhook-id. Répondez 2xx seulement après avoir enregistré durablement l’événement, puis traitez-le dans votre propre file. Une livraison réussie confirme la réponse HTTP du récepteur, pas le succès de votre traitement métier.

Les endpoints historiques restent identifiés par signing_version: 1 : ils utilisent les caractères du secret après whsec_ comme clé HMAC, sans décodage base64. Ils continuent de fonctionner jusqu’à rotation. Les nouveaux endpoints et ceux renouvelés portent signing_version: 2.

Lors d’une rotation, les signatures des deux secrets sont envoyées pendant une heure. Votre vérificateur doit accepter une signature valide parmi celles séparées par des espaces. Le nouveau secret est affiché une fois et secret_rotates_until indique la fin de transition. Une seconde rotation est bloquée pendant cette heure.

Recevoir sans doublons

La livraison est au moins une fois : dédupliquez par webhook-id, enregistrez l’événement durablement, puis répondez 2xx. Traitez-le ensuite dans votre file de travail. En cas d’échec, FRED réessaie avec des délais croissants, jusqu’à huit tentatives. Les redirections ne sont pas suivies.

Consultez les tentatives et relancez les échecs définitifs depuis le dashboard. Utilisez le GET de la commande pour réconcilier votre suivi si votre site a été indisponible.

Cette page vous a-t-elle été utile ?

Sur cette page