Journal des changements
Ce qui a changé dans l'API partenaire et dans les notifications, par date, avec le geste exact à faire quand une entrée casse un appel qui passait avant.
En quittant cette page, vous saurez ce qui a changé dans l'API partenaire et dans les notifications, à quelle date, et ce que vous avez à faire de votre côté quand un changement refuse un appel qui passait avant. Vous saurez aussi pourquoi le numéro de version que vous appelez ne bouge pas alors que ces entrées s'accumulent.
Lisez cette page en entier la première fois. Ensuite, revenez-y avant chaque évolution de votre intégration et arrêtez-vous à la première date que vous connaissez déjà.
#Comment cette page est faite
Vous lisez les entrées de la plus récente à la plus ancienne. La date portée par une entrée est celle de la mise en service du changement.
Une entrée commence par Rupture de compatibilité quand un appel qui passait avant est refusé après. C'est le seul cas où vous avez du travail. Les autres entrées décrivent un comportement qui s'ajoute ou une réponse qui devient plus précise, et votre intégration continue de fonctionner sans retouche.
Chaque entrée dit trois choses : ce qui change, la réponse exacte que vous recevez maintenant, et le geste à faire. Aucune entrée ne renvoie ailleurs pour le geste à faire.
Cette page couvre tous les points d'entrée que ce site documente : l'API partenaire à clef, les points d'entrée publics sans clef, les lectures de passeport authentifiées, les notifications envoyées à vos adresses et le portail partenaire. Elle ne couvre pas la console, dont les écrans évoluent sans contrat à tenir envers votre code.
#Pourquoi la version ne bouge pas
Le point d'entrée GET /v1/version répond toujours la même chose.
{
"version": "1.0.0",
"api_version": "v1"
}Les entrées ci-dessous s'inscrivent toutes dans la version 1. Le jour où une
évolution ne pourra pas y tenir, elle s'ajoutera sous /v2, et la version 1
gardera son comportement.
Les points d'entrée métier existent à deux adresses qui appellent le même
code : avec le préfixe /v1, et sans aucun préfixe. Appelez
GET /v1/version quand vous voulez la version de contrat. C'est le seul point
d'entrée de version que ce site documente.
Les deux adresses appellent le même code, donc elles reçoivent en même temps tous les changements de comportement listés ici. Une seule entrée fait exception, celle du 16 août 2026, qui ne concernait que les adresses sans préfixe.
Sur cette page
- Comment cette page est faite
- Pourquoi la version ne bouge pas
- 26 août 2026
- Rupture de compatibilité. Le niveau d'accès value_chain n'existe plus
- Le portail partenaire annonce le métier qu'il a servi
- L'image publique d'un exemplaire remonte à son modèle
- 22 août 2026
- Le certificat public nomme la marque émettrice
- Les refus d'authentification répondent en anglais
- Le portail partenaire a un plafond d'appels
- 21 août 2026
- L'envoi d'un lot crée maintenant des produits
- 20 août 2026
- Rupture de compatibilité. L'API refuse les champs owner_email et contract_address
- Rupture de compatibilité. Rejouer une clef d'idempotence avec un lot différent répond 409
- Rupture de compatibilité. Le suivi de lot exige le droit mint:batch
- Rupture de compatibilité. Modifier un abonnement aux notifications exige que votre offre les comprenne
- Un corps JSON illisible répond 400
- Les huit points d'entrée à clef sont plafonnés en débit
- Vos abonnements aux notifications restent lisibles et supprimables quelle que soit votre offre
- 16 août 2026
- Les adresses sans préfixe deviennent des alias permanents
- 14 août 2026
- Un fichier gzip abîmé répond 400
- Le suivi de lot rend quatre champs de plus quand la file a oublié votre lot
- 13 août 2026
- Une intervention du portail partenaire porte un niveau de preuve
- 11 août 2026
- Rupture de compatibilité. Supprimer un abonnement demande de retaper son adresse
- Chaque livraison porte le type d'événement
- 14 juillet 2026
- Deux en-têtes s'ajoutent à chaque livraison
- La signature porte les octets exacts qui vous sont envoyés
- 12 juillet 2026
- Les points d'entrée d'abonnement exigent des droits
- 15 mars 2026
- Le préfixe /v1 apparaît
- Ce que cette page ne fait pas
Trois changements. Le premier est une rupture de compatibilité, et il concerne tout partenaire accrédité.
- Rupture de compatibilité
#Le niveau d'accès
value_chainn'existe plusLe niveau
value_chainétait accordé à tout partenaire portant n'importe quelle accréditation sur la marque, et il rendait la réunion de ce que voient le réparateur, le recycleur et le fournisseur amont. Un recycleur accrédité y lisait donc les données de fabrication et la chaîne d'approvisionnement, que le niveaurecyclerlui refuse. Cette porte est fermée.Détail
Six niveaux subsistent :
public,end_user,repairer,recycler,upstreametauthority. Les trois niveaux de métier sont des publics distincts : détenir une accréditation n'en ouvre aucune autre.La réponse exacte.
?access_tier=value_chainrépond maintenant 422, surGET /v1/passport/{identifier}, surGET /v1/passport/01/{gtin}et sur les trois points d'entrée d'identité vérifiable.detailest la liste de validation habituelle, chaque entrée portantloc,typeetmsg, etlocnommeaccess_tier.Ce que vous faites. Demandez le niveau de votre métier,
repairerourecycler. Vous recevrez moins de champs qu'avant, et ce sont précisément les champs qui ne relèvent pas de votre métier. - Changement
#Le portail partenaire annonce le métier qu'il a servi
Dans
GET /v1/partner-portal/products/{identifier}, le champpassport.access_tiervalait toujoursvalue_chain. Il porte maintenant les métiers réellement servis, joints par un+et rangés par ordre alphabétique :recycler, ourepairer+recyclerpour un compte qui porte les deux accréditations sur cette marque. Il vautpublicquand la marque ne vous en a reconnu aucune, et le passeport est alors filtré au niveau public.Détail
Ce que vous faites. Si votre code compare cette valeur à
value_chain, reprenez la comparaison. Et attendez-vous à un contenu plus étroit qu'avant : il est désormais filtré sur vos seules accréditations. - Changement
#L'image publique d'un exemplaire remonte à son modèle
Dans
GET /v1/products/{uid_hash}/public, le champimage_urlne regardait que les médias attachés directement à l'exemplaire, et valaitnulldès qu'il n'en avait aucun. Il suit maintenant la même chaîne de repli que le reste du site : une image de l'exemplaire, puis l'image principale de son modèle, puis les médias du modèle.Détail
Ce que vous faites. Rien. Un champ qui valait
nullpeut désormais porter une adresse.
Trois changements sont partis ensemble. Aucun n'est une rupture de compatibilité.
- Changement
#Le certificat public nomme la marque émettrice
Le champ
issuer_nameporte le nom de la marque qui a émis le certificat. Le serveur le calcule à la lecture, et il vautnullquand le certificat n'est rattaché à aucune marque.Détail
Trois surfaces sont concernées :
GET /v1/certificate/{identifier}, le PDF rendu parGET /v1/certificate/{identifier}/download, et le bloccertificatedeGET /v1/resolve/{identifier}.Ce que vous faites. Rien dans vos appels. Si vous avez recopié la valeur de
issuer_namedans votre propre base, remplacez-la par ce que rend l'API aujourd'hui. - Changement
#Les refus d'authentification répondent en anglais
La porte d'entrée de l'API rendait ses messages en deux langues selon le chemin appelé. Les messages qu'elle pose dans
detailsont désormais en anglais :Not authenticated,Invalid token,Invalid token: missing email,Token has been revoked,Invalid JWT token,Account disabled,User not foundetPartner account required (repairer or recycler).Détail
Deux refus de
POST /v1/originality/read-sig/verifysuivent la même règle et valent maintenantInvalid uid_hexetInvalid signature_hex.Ce que vous faites. Rien, si vous branchez votre code sur le code HTTP, comme le recommande la page des erreurs. Un client qui compare ces phrases caractère par caractère doit reprendre ses comparaisons, ou mieux, les supprimer.
- Changement
#Le portail partenaire a un plafond d'appels
Les quatre points d'entrée
/partner-portalacceptent 30 appels par fenêtre de 60 secondes, comptés par adresse d'appel. Les quatre partagent ce compteur, et la forme/v1/partner-portal/...le partage avec la forme sans préfixe.Détail
Chaque réponse acceptée porte
X-RateLimit-Limit,X-RateLimit-RemainingetX-RateLimit-Reset. Un dépassement renvoie 429, avecdetailvalantRate limit exceeded: 30 requests per 60set un en-têteRetry-Aftervalant60.Ce que vous faites. Espacez vos appels au portail et pilotez votre cadence sur
X-RateLimit-Remaining. Un parcours humain, chercher un produit puis déclarer une intervention, reste très en dessous de ce plafond.
- Changement
#L'envoi d'un lot crée maintenant des produits
POST /v1/partner/mint/batchrépondait200, son traitement allait jusqu'au bout, et aucun produit n'était créé. Il manquait à chaque ligne deux valeurs que le contrat d'envoi ne vous laisse pas fournir, et chaque ligne était rejetée pour cette raison.Détail
Le serveur pose désormais ces deux valeurs lui-même, sur chaque ligne : la méthode d'identification
qret l'identifiant technique du produit.Ce que vous faites. Rien dans vos envois. Le contrat d'une ligne ne change pas, et une ligne qui porterait la méthode d'identification ou l'identifiant technique est refusée en
400, comme tout champ que le contrat ne nomme pas.Les produits créés par cette voie sont identifiés par QR. Pour des articles NFC, passez par la console.
Sept changements sont partis ensemble. Les quatre premiers sont des ruptures de compatibilité.
- Rupture de compatibilité
#L'API refuse les champs
owner_emailetcontract_addressUne ligne de lot qui porte l'un de ces deux champs fait échouer toute la requête en
400. La réponse nomme le champ refusé.Détail
L'API acceptait ces deux champs et ne les lisait jamais. La valeur que vous y mettiez n'avait aucun effet.
Une ligne de lot accepte désormais cinq champs et rien d'autre :
product_name,brand_id,category_idetmetadata_uri, qui sont obligatoires, etexternal_ref, qui est facultatif.Ce que vous faites. Retirez ces deux colonnes de vos exports CSV et ces deux clefs de vos objets JSON. Si vous avez besoin de rattacher une ligne à une référence de votre côté, utilisez
external_ref: c'est le seul champ libre du contrat. Nous le conservons sur la ligne du lot et nous le rendons dans le résultat que litGET /v1/partner/mint/batch/status/{job_id}. Aucun champ de produit ne le reprend.Ce retrait fait passer la validation. Depuis le 21 août 2026, il fait aussi créer les produits, voir l'entrée de cette date.
- Rupture de compatibilité
#Rejouer une clef d'idempotence avec un lot différent répond 409
L'en-tête
Idempotency-Keyreste facultatif et reste mémorisé 24 heures.Détail
Rejouer la même valeur avec le même lot rend toujours la réponse du premier appel, sans rien refrapper. L'ordre des contrôles a changé le même jour. Le rejeu consomme désormais un jeton de votre plafond de débit, et l'API relit votre corps de requête avant de vous rendre la réponse mise en cache. Un rejeu au-delà du plafond reçoit donc
429. Un rejeu dont le corps est devenu illisible reçoit400.Rejouer la même valeur avec un lot différent répond maintenant
409. L'API ne met pas votre second lot en file, et la réponse vous le dit.JSON { "detail": "Idempotency-Key 'lot-2026-08-20-a' was already used with a different request body" }Le même code
409signale aussi qu'un appel portant cette clef est encore en cours de traitement. Le message est alorsA request with this Idempotency-Key is already being processed. Lisez le message avant de décider quoi faire : le premier cas vous demande de changer votre clef, le second vous demande d'attendre la fin du traitement en cours.L'égalité de deux lots porte sur leur contenu une fois lu. L'ordre des lignes, l'ordre des colonnes, le choix entre CSV et JSON et les cellules vides n'y changent rien.
Ce que vous faites. Fabriquez une valeur d'
Idempotency-Keypar lot distinct. Si votre code réutilise une valeur fixe, ou une valeur dérivée de l'heure à la minute, changez-la maintenant. - Rupture de compatibilité
#Le suivi de lot exige le droit
mint:batchGET /v1/partner/mint/batch/status/{job_id}exige le droitmint:batch, le même que l'envoi du lot. Une clef qui ne le porte pas reçoit403, et le message nomme le droit manquant.Détail
Ce que vous faites. Vérifiez que la clef qui interroge le suivi porte
mint:batch. Les droits d'une clef se fixent à sa création et aucun écran ne les modifie ensuite, donc il vous faut une nouvelle clef.Vérifiez d'abord votre plafond de clefs, qui ne compte que les clefs actives. L'offre Essentiel n'en autorise qu'une seule : révoquez l'ancienne, puis créez la nouvelle, en acceptant la coupure entre les deux. L'offre Prestige en autorise cinq : créez la nouvelle, déployez-la, puis révoquez l'ancienne. Révoquer une clef libère immédiatement une place. Une création au-delà du plafond répond
403avec le codeQUOTA_EXCEEDED. - Rupture de compatibilité
#Modifier un abonnement aux notifications exige que votre offre les comprenne
PUT /v1/partner/webhooks/{webhook_id}regarde désormais l'offre de votre marque. Un appel qui passait la veille pour une marque dont l'offre ne comprend pas les notifications est refusé en403.Détail
JSON { "detail": { "code": "FEATURE_NOT_AVAILABLE", "feature": "webhooks" } }Une extinction seule fait exception : envoyer
is_activeàfalseet rien d'autre reste possible sans l'offre. Dès qu'un autre champ accompagne cette extinction, l'API exige l'offre.La création d'un abonnement,
POST /v1/partner/webhooks, répond la même chose et l'exigeait déjà avant ce changement.Ce que vous faites. Rien si votre offre comprend les notifications. Si elle ne les comprend plus, arrêtez de modifier vos abonnements : éteignez-les avec
is_activeàfalseseul, ou supprimez-les. - Changement
#Un corps JSON illisible répond 400
Un corps mal formé envoyé à
POST /v1/partner/mint/batchrépond maintenant400, avec un message qui rappelle les deux formats acceptés.Détail
JSON { "detail": "Corps de requete illisible : le JSON envoye est mal forme. Envoyez une liste d'objets produit en application/json, ou un fichier CSV en multipart/form-data." }Ce que vous faites. Si votre code rejoue automatiquement les réponses de la famille
5xx, ce cas ne le déclenche plus. Une requête refusée en400est à corriger, et la rejouer telle quelle donnera le même refus. - Changement
#Les huit points d'entrée à clef sont plafonnés en débit
Le plafond d'appels s'applique maintenant aux huit points d'entrée de l'API partenaire, y compris le suivi de lot et les cinq points d'entrée d'abonnement aux notifications.
Détail
Deux conséquences visibles. Au-delà du plafond, vous recevez
429avec l'en-têteRetry-After, exprimé en secondes. Quand le service de plafonnement est indisponible, vous recevez503, et l'appel n'a aucun effet : une suppression refusée ainsi ne supprime rien.Les réponses qui passent portent
X-RateLimit-Limit,X-RateLimit-Remaining,X-RateLimit-ResetetX-RateLimit-Scope.Ce que vous faites. Lisez
X-RateLimit-Remaininget ralentissez avant d'atteindre zéro. Si vous interrogez le suivi d'un lot en boucle, espacez vos appels : c'est le point d'entrée le plus exposé à ce plafond. Traitez le503comme une indisponibilité passagère et réessayez après un délai. - Changement
#Vos abonnements aux notifications restent lisibles et supprimables quelle que soit votre offre
Lire la liste de vos abonnements, lire un abonnement et supprimer un abonnement fonctionnent quelle que soit l'offre de votre marque. Ces trois appels ne regardent pas votre offre.
Détail
L'envoi des notifications suit une autre règle : une marque dont l'offre ne comprend plus les notifications ne reçoit plus de livraison, quels que soient les abonnements encore enregistrés.
Ce que vous faites. Rien. Si votre offre ne comprend plus les notifications, vous gardez la main pour inventorier vos abonnements et pour les supprimer.
- Changement
#Les adresses sans préfixe deviennent des alias permanents
Les copies sans préfixe
/v1répondaient avec deux en-têtes qui annonçaient une fin de service au 1er septembre 2026,DeprecationetSunset. L'API n'envoie plus ces deux en-têtes. Les adresses en/v1ne les ont jamais portés.Détail
Aucune date de fin de service n'est attachée à ces adresses. Si votre intégration les appelle déjà, elle continue de fonctionner.
Ce que vous faites. Rien dans l'immédiat. Utilisez la forme
/v1pour toute nouvelle intégration : c'est la forme documentée partout sur ce site.
- Changement
#Un fichier gzip abîmé répond 400
POST /v1/partner/mint/batchaccepte un CSV compressé en gzip ou en zlib.Détail
Un fichier gzip que le serveur ne parvient pas à décompresser répond maintenant
400, avec le motif dans le message. C'est une erreur de la requête, et votre code peut la traiter comme telle.Un fichier dont le contenu une fois décompressé dépasse le plafond répond
413, et le message indique ce plafond en Mio.Ce que vous faites. Rien si vos envois sont valides. Si vous compressez à la volée, vérifiez que le flux est complet avant de l'envoyer, et découpez vos lots pour rester sous le plafond. Un lot porte au plus 500 articles.
- Changement
#Le suivi de lot rend quatre champs de plus quand la file a oublié votre lot
GET /v1/partner/mint/batch/status/{job_id}répondaitunknownau propriétaire d'un lot ancien, une fois la durée de rétention de la file écoulée. Il rend maintenant le statut réel, reconstruit à partir de la réservation enregistrée à l'envoi du lot, et il ajoute quatre champs :batch_status,items_count,success_counteterror_count.Détail
Un identifiant qui ne désigne aucun lot de votre marque répond toujours
unknown, sans rien révéler de plus.Ce que vous faites. Rien, ces champs s'ajoutent.
- Changement
#Une intervention du portail partenaire porte un niveau de preuve
POST /v1/partner-portal/interventionsenregistre désormais un niveau de preuve avec chaque intervention, dans le champproof_level.Détail
Le corps de la requête accepte un champ facultatif
proof_code. Sans lui, le niveau vautdeclared. Avec un code valide, il vautcustomer_codequand le code a été lu par le client, ouwork_orderquand il vient de l'ordre de travail de la marque. Un code refusé répond422et n'enregistre rien du tout : ni l'intervention, ni la consommation du code.Les interventions enregistrées avant cette date rendent
proof_levelvide. Une valeur vide ne vaut pasdeclared: la question n'avait pas été posée.Ce que vous faites. Si vous affichez l'historique des interventions, traitez la valeur vide comme un cas à part et n'affichez pas « déclaré » à sa place.
- Rupture de compatibilité
#Supprimer un abonnement demande de retaper son adresse
DELETE /v1/partner/webhooks/{webhook_id}exige un paramètre d'URLconfirmqui contient l'adresse exacte de l'abonnement.Détail
Sans ce paramètre, un abonnement qui vous appartient répond
400avec le codeCONFIRMATION_REQUIRED. Avec une valeur qui ne correspond pas, la réponse est400avec le codeCONFIRMATION_MISMATCH, et l'API ne modifie rien. Une suppression réussie répond204.Un identifiant qui ne désigne aucun abonnement de votre marque répond
404, que vous ayez envoyéconfirmou non : l'API cherche votre abonnement avant de regarder votre confirmation.Un appel qui n'envoyait que l'identifiant est donc refusé.
Ce que vous faites. Lisez l'adresse avec
GET /v1/partner/webhooks/{webhook_id}, puis renvoyez-la dansconfirm.curl curl -X DELETE \ "https://api.sealtrust.io/v1/partner/webhooks/1?confirm=https%3A%2F%2Fexemple-sas.example%2Fwebhooks%2Fsealtrust" \ -H "Authorization: Bearer st_test_0000000000000000000000000000000000000000000000" - Changement
#Chaque livraison porte le type d'événement
Chaque livraison porte maintenant
X-Webhook-Event, qui nomme le type d'événement. La signature ne couvre pas cet en-tête.Détail
Ce que vous faites. Rien, cet en-tête s'ajoute.
- Changement
#Deux en-têtes s'ajoutent à chaque livraison
Chaque livraison porte maintenant
X-Webhook-IdetX-Webhook-Timestamp, en plus deX-Webhook-Signature.Détail
X-Webhook-Idest l'empreinte du corps de la livraison. Les réessais d'une même livraison portent la même valeur, ce qui vous permet d'écarter un réessai. Deux événements distincts dont le corps est identique portent eux aussi la même valeur.Ce que vous faites. Dédoublonnez sur le couple formé du nom de l'événement, porté par
X-Webhook-Eventdepuis le 11 août 2026, et deX-Webhook-Id. N'écartez jamais une livraison sur la valeur deX-Webhook-Timestamp: cet horodatage change à chaque réessai, donc il vous ferait traiter deux fois la même livraison. - Changement
#La signature porte les octets exacts qui vous sont envoyés
X-Webhook-Signaturea la formet=<horodatage>,v1=<empreinte>. L'empreinte est un HMAC-SHA256 calculé avec le secret de votre abonnement, sur la chaîne formée de l'horodatage, d'un point, et du corps de la requête.Détail
Le corps signé est la suite d'octets reçue sur le fil. Décoder le JSON puis le réencoder avant de vérifier casse la signature, parce que le réencodage ne rend pas les mêmes octets.
Ce que vous faites. Vérifiez la signature sur le corps brut de la requête, avant tout décodage.
- Changement
#Les points d'entrée d'abonnement exigent des droits
Lister vos abonnements et en lire un exigent le droit
webhooks:read. Créer, modifier et supprimer un abonnement exigent le droitwebhooks:write.Détail
Une clef qui ne porte pas le droit reçoit
403, et le message nomme le droit manquant.Ce que vous faites. Vérifiez les droits de la clef qui gère vos abonnements. Si elle a été créée avec le seul droit
mint:batch, créez une nouvelle clef portant aussi les droits de notification.
- Changement
#Le préfixe
/v1apparaîtChaque point d'entrée métier devient joignable à deux adresses, avec le préfixe
/v1et sans aucun préfixe.Détail
Les adresses sans préfixe répondent en plus deux en-têtes,
Deprecation: trueetSunset: 2026-09-01. Les adresses en/v1ne les portent pas. L'entrée du 16 août 2026 retire ces deux en-têtes et aucune date de fin de service n'a été appliquée.Ce que vous faites. Rien. Les deux adresses appellent le même code.
#Ce que cette page ne fait pas
Elle n'annonce pas les changements à venir. Une entrée arrive ici quand le comportement décrit est en service.
Elle ne remplace pas un essai. Nous n'ouvrons aucun environnement de test aux partenaires, et aucune adresse de bac à sable n'existe. Après avoir lu une entrée marquée rupture, rejouez votre appel réel sur un produit ou un abonnement de votre marque que vous pouvez sacrifier, et comparez le code de réponse à celui que vous attendiez.
Cette page vous a-t-elle été utile ?
Votre réponse ouvre un courriel pré-rempli dans votre messagerie, à destination de contact@sealtrust.io. Vous le relisez avant de l'envoyer.