Méthode POST/partner/webhooks

Enregistrer une adresse HTTPS qui recevra les événements de votre marque, et choisir les types d'événements envoyés à cette adresse. Droit webhooks:write.

Sur cette page

Vous enregistrez une adresse HTTPS qui recevra les événements de votre marque, et vous choisissez les types d'événements envoyés à cette adresse. L'abonnement appartient à la marque de la clef qui appelle. En quittant cette page, vous saurez quels types d'événements partent réellement aujourd'hui, comment vérifier la signature d'une livraison, et quelle réponse votre intégration reçoit à chaque refus.

Adresse complète :

HTTP
POST https://api.sealtrust.io/v1/partner/webhooks

Le même point d'entrée répond aussi sans le préfixe /v1, à https://api.sealtrust.io/partner/webhooks. Les deux adresses appellent le même code et les deux sont permanentes. Utilisez la forme /v1 pour une nouvelle intégration.

#Autorisation

Clef d'API dans l'en-tête Authorization, au format Bearer suivi d'un espace puis de la clef.

Ce qui est exigéValeur
Authentificationclef d'API de votre marque
Droit porté par la clefwebhooks:write
Fonctionnalité de votre offreles notifications par webhook, comprises à partir de l'offre Prestige, absentes de l'offre Essentiel

Les offres Prestige, Maison et Inside portent les notifications par webhook. L'offre Essentiel ne les porte pas, et le compte d'essai non plus. Si votre offre ne les porte pas, vous recevez un 403 sur cette route.

La clef décide de la marque. Vous ne pouvez pas créer un abonnement pour une autre marque que la sienne, et aucun champ du corps ne permet de la changer.

Un droit manquant renvoie 403 sans rien créer.

#Plafond d'appels

Nous mesurons le débit sur une fenêtre fixe de 60 secondes. Le plafond dépend de votre offre, et nous pouvons le relever pour votre marque sans changer votre abonnement. Lisez la valeur du moment dans l'en-tête X-RateLimit-Limit de chaque réponse acceptée. Quand aucune valeur n'est posée sur votre marque ni sur votre offre, la valeur de repli est de 120 appels par fenêtre.

Deux compteurs se superposent, avec le même plafond : un par clef, un pour la somme de toutes les clefs de votre marque. Créer une clef de plus n'augmente donc pas le débit total autorisé.

En-têteContenu
X-RateLimit-Limitle plafond appliqué sur la fenêtre
X-RateLimit-Remainingce qu'il vous reste dans la fenêtre en cours
X-RateLimit-Resetl'horodatage de fin de la fenêtre, en secondes
X-RateLimit-Scopekey ou brand, le compteur le plus contraignant des deux

Un dépassement renvoie 429 avec ces quatre en-têtes, plus Retry-After. Retry-After compte les secondes qui restent dans la fenêtre en cours, et vaut au minimum 1.

#Paramètres de chemin et de requête

Aucun. Ce point d'entrée ne lit ni paramètre de chemin, ni paramètre de requête. Tout est dans le corps.

#Corps de la requête

Content-Type application/json.

NomTypeObligatoireDescription
urlstringouiL'adresse qui recevra les événements. Elle doit commencer par https:// et mesurer de 10 à 2048 caractères.
eventsstring[]nonLes types d'événements auxquels vous vous abonnez. Chaque valeur doit figurer dans la liste ci-dessous. Absent ou vide, l'abonnement ne reçoit jamais rien.
secretstringnonLe secret partagé qui signe chaque livraison. 128 caractères au maximum. Absent, les livraisons partent sans signature.

Le corps n'accepte que ces trois noms. Tout autre champ fait échouer la requête en 422.

#Les 23 types d'événements acceptés

Un nom absent de ces deux listes fait échouer la requête en 422.

#Les 17 types que nous livrons aujourd'hui

Cycle de vie d'un article

product.minted, product.transferred, transfer.accepted

Scans et sécurité

product.scanned, product.gray_market, clone.alert

Retours et garantie

return.requested, return.received, return.completed, return.rejected, return.expired, warranty.claimed

Rachat

buyback.offered, buyback.accepted, buyback.declined, buyback.completed, buyback.expired

#Les 6 types acceptés à l'abonnement et jamais émis

product.burned, product.status_changed, batch.completed, batch.failed, certificate.issued, warranty.expiring_soon

Ces six noms passent le contrôle de saisie et s'inscrivent dans votre abonnement. Aucun code du produit ne les émet à ce jour, donc votre adresse ne recevra jamais de livraison portant l'un de ces noms. Ne construisez aucune alerte ni aucun automatisme dessus. Nous mettrons cette liste à jour le jour où l'un d'eux partira.

#Ce que fait le secret

Quand vous fournissez un secret, chaque livraison porte l'en-tête X-Webhook-Signature, au format t=<horodatage>,v1=<empreinte>. L'empreinte est un HMAC-SHA256 calculé avec votre secret sur la chaîne composée de l'horodatage, d'un point, puis du corps reçu octet pour octet. Vérifiez la signature sur les octets bruts que vous recevez, avant de décoder le JSON.

Trois autres en-têtes accompagnent chaque livraison.

En-têteContenuCouvert par la signature
X-Webhook-Eventle type d'événement livré, par exemple product.scannednon
X-Webhook-Idun identifiant stable pour un même événement, qui vous sert à écarter les doublons de renvoinon
X-Webhook-Timestampl'horodatage utilisé dans la signature, en secondesoui

X-Webhook-Event vous dit de quel événement il s'agit quand un abonnement porte sur plusieurs types. Il reste hors de la signature, donc il n'authentifie rien. Quand votre récepteur doit aiguiller sur une valeur authentifiée, enregistrez une adresse par type d'événement, et servez-vous de cet en-tête seulement pour lire vos journaux.

Sans secret, l'en-tête X-Webhook-Signature est absent de vos livraisons.

#Requête d'exemple

Les trois programmes font la même chose : ils enregistrent une adresse pour deux types d'événements réellement livrés, avec un secret de signature.

curl -X POST https://api.sealtrust.io/v1/partner/webhooks \
  -H "Authorization: Bearer st_test_0000000000000000000000000000000000000000000000" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://exemple-sas.example.com/sealtrust/evenements",
    "events": ["product.scanned", "clone.alert"],
    "secret": "secret-partage-a-remplacer"
  }'

#Réponse d'exemple

Code HTTP 201Created

Une création réussie répond 201 Created.

201 Created
{
  "id": 41,
  "brand_id": 12,
  "url": "https://exemple-sas.example.com/sealtrust/evenements",
  "events": ["product.scanned", "clone.alert"],
  "is_active": true,
  "health": "healthy",
  "created_at": "2026-08-20T09:14:03.512841+00:00",
  "updated_at": "2026-08-20T09:14:03.512841+00:00"
}
ChampTypeCe qu'il contient
idintegerL'identifiant de l'abonnement. C'est lui que vous passerez aux routes de lecture, de modification et de suppression.
brand_idintegerLa marque propriétaire, celle de votre clef.
urlstringL'adresse enregistrée. C'est cette valeur exacte que la suppression vous demandera de recopier.
eventsstring[]Les types d'événements souscrits.
is_activebooleantrue à la création. Une modification peut le passer à false pour éteindre l'abonnement sans le supprimer.
healthstringhealthy à la création. Passe à degraded quand la série de renvois abandonne votre adresse, et revient à healthy à la première livraison réussie.
created_atstringDate et heure de création, au format ISO 8601.
updated_atstringDate et heure de la dernière modification, au format ISO 8601.

#Erreurs

Le corps d'une réponse d'erreur contient un seul champ, detail.

CodeConditionCe que vous devez faire
401L'en-tête Authorization est absent. detail vaut "Missing Authorization header", et la réponse porte WWW-Authenticate: Bearer.Ajoutez l'en-tête Authorization: Bearer <votre clef>.
401L'en-tête ne commence pas par Bearer suivi d'un espace. detail vaut "Invalid Authorization header format (expected 'Bearer <token>')", et la réponse porte WWW-Authenticate: Bearer.Respectez le mot Bearer, un espace, puis la clef.
401La valeur envoyée est vide ou fait moins de 40 caractères. detail vaut "Invalid API key format".Vérifiez que la clef a été copiée en entier.
401La clef ne correspond à aucune clef connue. detail vaut "Invalid API key".La clef est fausse ou a été supprimée. Créez-en une depuis la console de votre marque.
403La clef n'est plus active. detail reprend son état, par exemple "API key is revoked".Utilisez une clef active.
403La clef a dépassé sa date d'expiration. detail vaut "API key has expired".Créez une nouvelle clef. La clef bascule en expirée dès ce refus.
403La clef ne porte pas le droit exigé. detail vaut "Missing required scope: webhooks:write".Créez une clef qui porte ce droit.
403Votre offre ne comprend pas les notifications. detail est un objet dont code vaut FEATURE_NOT_AVAILABLE et feature vaut webhooks.Passez sur une offre qui les porte. Rejouer la requête ne change rien.
422La validation refuse le corps quand : url est absente, url ne commence pas par https://, url sort des bornes de 10 à 2048 caractères, un type d'événement est inconnu, secret dépasse 128 caractères, ou un champ inconnu est présent. detail est une liste, et chaque entrée porte loc, type et msg.Lisez loc pour savoir quelle valeur est refusée, corrigez-la, rappelez.
429Votre clef dépasse son plafond de débit. detail commence par Rate limit exceeded, et X-RateLimit-Scope vaut key.Attendez le nombre de secondes indiqué par Retry-After, puis rappelez.
429La somme des clefs de votre marque dépasse le plafond. detail commence par Brand rate limit exceeded, et X-RateLimit-Scope vaut brand.Attendez Retry-After. Créer une clef de plus n'augmente pas ce plafond.
503Le service qui tient les compteurs de débit est momentanément indisponible. detail vaut "Rate limiting temporarily unavailable, please retry shortly".Nous n'avons rien créé. Réessayez plus tard.
500Une panne de notre côté. detail vaut "Internal Server Error", ou "Internal server error" quand la panne survient pendant la lecture de votre clef.Réessayez. Si le refus persiste, envoyez-nous l'en-tête X-Request-Id de la réponse.

#Voir aussi

Votre réponse ouvre un courriel pré-rempli dans votre messagerie, à destination de contact@sealtrust.io. Vous le relisez avant de l'envoyer.

Proposer une correctionSignaler un problème