API partenaire, vue d'ensemble

Adresse de base, authentification par clef, droits, plafonds d'appels, rejeu d'un appel sans doubler son effet, pagination et versionnage. La page à lire avant d'ouvrir la référence.

Sur cette page

En quittant cette page, vous saurez authentifier un appel à l'API partenaire, choisir la bonne adresse, lire les en-têtes qui vous disent combien d'appels il vous reste, rejouer une requête sans doubler son effet, et reconnaître les trois plafonds qui peuvent vous refuser. C'est la page à lire une fois, avant d'ouvrir la référence point d'entrée par point d'entrée.

#Ce que cette API fait

L'API partenaire à clef sert à piloter SealTrust depuis votre propre système, sans passer par la console. Elle compte vingt-deux points d'entrée, répartis en cinq usages.

UsagePoints d'entrée
Créer des produits en lot, suivre l'avancement du traitement, et lire les pièces créées3
Déclarer une vente au client final1
Gérer vos abonnements aux notifications5
Préremplir votre catalogue : modèles, lots, passeports brouillons, score de complétude7
Afficher le passeport dans votre propre page : passeport, preuve et signature en un appel, scans et lectures NFC de vos visiteurs6

Le catalogue a sa page : Remplir le catalogue par l'API. L'affichage aussi : Afficher le passeport dans votre page.

L'envoi d'un lot ne crée que des produits identifiés par QR. Le serveur pose lui-même, sur chaque ligne du lot, la méthode d'identification et l'identifiant technique de l'article. Vos lignes ne portent ni l'un ni l'autre, et vous ne pouvez pas en demander d'autres.

Les pièces créées par un lot se lisent ligne par ligne avec GET /partner/mint/batch/{job_id}/items : pour chaque ligne, votre external_ref, son état, le numéro de série, le numéro de jeton et le lien à imprimer dans le QR code. Une ligne qui a échoué le dit, sans le détail technique : donnez-nous le job_id et le row_index. Le numéro de jeton, token_id, arrive après les autres champs : il reste null tant que la chaîne n'a pas confirmé la frappe, y compris sur un lot déjà finished, et se remplit en général quelques secondes plus tard. Relisez la liste pour l'obtenir. Le numéro de série et le lien à imprimer, eux, sont là dès que la ligne est créée : vous pouvez imprimer sans attendre le jeton. La liste est paginée par limit (100 par défaut, 500 au plus) et offset, et demande le droit mint:batch. Un lot d'une autre marque et un identifiant inconnu reçoivent le même 404. Sur un lot frappé avec issue_purchase_codes=true, chaque ligne porte aussi le code d'achat de la pièce, une seule fois (émettre les codes d'achat).

Vos modèles se lisent par le catalogue. Le passeport publié d'un produit, avec sa preuve et sa signature, se lit en un appel par GET /partner/passports/{identifier}. Les points d'entrée publics de vérification, qui ne demandent aucune clef, restent ouverts à tous.

Le portail partenaire, à l'adresse /partner-portal, est une surface différente. Il s'authentifie avec la session d'un compte partenaire réparateur ou recycleur, et une clef d'API n'y donne aucun accès.

#Ce qui se fait dans la console seulement

Une clef d'API ne règle pas votre compte. Les gestes ci-dessous n'ont aucun point d'entrée dans cette API : faites-les une fois dans la console, avec un compte administrateur, puis pilotez le reste par l'API.

GesteOù, dans la console
Créer une marque clienteVos marques clientes
Inviter une personne dans l'équipe d'une marqueL'équipe et les rôles
Créer ou révoquer une clef d'API, y compris la clef d'une marque clienteClés d'API et webhooks
Déclarer les adresses de votre page, la page qui affiche un passeport et l'envoi des scans vers elleClés d'API et webhooks
Poser le logo et les couleurs, masquer notre mentionLa marque et son apparence
Ajouter et faire vérifier un domaine personnaliséLe domaine personnalisé
Lire le relevé d'usage mensuel de vos marques clientesLe relevé d'usage de vos marques clientes

Une clef qui appelle l'adresse d'un de ces écrans est refusée : ces adresses demandent une session de la console, pas une clef.

#Le contrat OpenAPI

Le contrat des points d'entrée partenaires se télécharge au format OpenAPI : openapi-partner.json. Il est produit à partir du code de l'API à chaque version de ce site, déclare l'authentification par clef (Authorization: Bearer) sur chaque point d'entrée, et décrit les deux formes du corps de POST /v1/partner/mint/batch : la liste JSON et le fichier CSV. Servez-vous-en pour générer un client. Les guides de ce site restent la référence pour les règles et les refus. L'API ne sert pas de page Swagger en production.

#L'adresse de base et le préfixe /v1

Vous appelez l'API sur https://api.sealtrust.io.

Chaque point d'entrée décrit sur ce site existe à deux adresses qui appellent exactement le même code : avec le préfixe /v1, et sans aucun préfixe.

HTTP
POST https://api.sealtrust.io/v1/partner/mint/batch
POST https://api.sealtrust.io/partner/mint/batch

Utilisez la forme /v1 pour toute nouvelle intégration.

Les pages de référence de ce site titrent chaque point d'entrée avec son chemin sans préfixe, par exemple POST /partner/mint/batch. Ajoutez /v1 devant ce chemin quand vous écrivez votre appel.

Les adresses sans préfixe sont des alias permanents. Nous ne leur attachons aucune date de fin de service, et nous n'envoyons sur ces réponses aucun en-tête d'annonce de suppression. Si votre intégration les appelle déjà, elle continuera de fonctionner.

#Authentifier un appel

Vous envoyez votre clef dans l'en-tête Authorization, au format Bearer.

HTTP
Authorization: Bearer votre_clef

C'est le seul mode d'authentification de cette API. Il n'y a ni paramètre d'URL ni cookie. Deux points d'entrée, qui enregistrent un scan fait par l'un de vos visiteurs, demandent en plus quatre en-têtes signés qui nomment ce visiteur : ils sont décrits dans Afficher le passeport dans votre page.

#Obtenir une clef

Vous créez vos clefs depuis la console de votre marque, dans Paramètres puis l'onglet Développeurs. L'onglet reste visible quelle que soit votre offre. Si votre offre ne comprend pas l'accès API, l'écran s'affiche verrouillé et vous ne pouvez y créer aucune clef.

Trois points comptent au moment de la création.

  • Le secret complet ne s'affiche qu'une seule fois, dans la fenêtre qui suit la création. Copiez-le à ce moment. Aucun écran et aucun point d'entrée ne permet de le relire ensuite. Nous n'en conservons qu'une empreinte.
  • Une clef appartient à une seule marque. Nous rattachons à cette marque toutes les opérations faites avec elle, et à aucune autre.
  • Votre clef commence par st_live_. Il n'existe ni clef de test ni bac à sable : chaque appel agit pour de vrai, une frappe est ancrée et compte dans votre quota. Les exemples de cette documentation montrent st_live_ suivi de zéros, qui n'est la clef de personne.
  • Une clef expire toujours. Vous choisissez une durée de vie à la création. Si vous n'en choisissez pas, elle est de 365 jours. Notez la date dans votre agenda : le jour venu, vos appels s'arrêtent.
  • Votre offre plafonne le nombre de clefs utilisables. Une clef révoquée ou arrivée à sa date d'expiration ne compte plus. Pour changer de clef sans coupure, créez la nouvelle avant de révoquer l'ancienne : pendant ce temps, les deux occupent une place. Si votre offre n'en permet qu'une, la rotation passe par une coupure, entre la révocation de l'ancienne et la mise en service de la nouvelle.

La console affiche ensuite les premiers caractères de chaque clef, pour vous permettre de la reconnaître dans la liste sans jamais réafficher son secret. Elle affiche aussi la date de dernière utilisation. Nous ne rafraîchissons cette date qu'au plus une fois par minute, elle peut donc retarder d'une minute sur votre dernier appel.

#Révoquer une clef

Vous révoquez une clef depuis la même page, et la révocation prend effet immédiatement. Le premier appel qui suit reçoit un refus. Révoquer une clef libère une place si votre offre limite le nombre de clefs actives.

#Les refus d'authentification

CodeCe qui s'est passéQue faire
401l'en-tête Authorization est absentajoutez-le, la réponse porte aussi WWW-Authenticate: Bearer
401l'en-tête ne commence pas par Bearer suivi d'un espacecorrigez la forme de l'en-tête
401la clef est mal formée ou inconnuerenvoyez le secret complet tel que la console l'a affiché, sans espace ni retour à la ligne
403la clef a été révoquéecréez une nouvelle clef dans la console
403la clef a atteint sa date d'expirationcréez une nouvelle clef, l'ancienne ne redeviendra jamais valide
403la clef n'a pas le droit requis par ce point d'entréele message nomme le droit manquant, voir les droits attachés à une clef

#Votre premier appel

Vérifiez qu'une clef fonctionne avec la liste de vos abonnements aux notifications. Ce point d'entrée ne modifie rien et ne consomme aucun quota. Il demande le droit webhooks:read.

curl -i https://api.sealtrust.io/v1/partner/webhooks \
  -H "Authorization: Bearer st_live_0000000000000000000000000000000000000000000000"

Réponse, code HTTP 200, pour une marque qui n'a encore aucun abonnement :

JSON
{
  "items": [],
  "total": 0
}

Le SDK TypeScript vous rend le corps de la réponse, jamais ses en-têtes. Pour lire les en-têtes de plafond décrits dans Le débit, en appels par minute, appelez l'API en HTTP direct depuis votre serveur, ou passez par curl -i. Un navigateur ne peut pas les lire : nous n'exposons au navigateur que l'en-tête X-Total-Count.

#Les droits attachés à une clef

Chaque clef porte une liste de droits. Un droit absent fait refuser l'appel en 403, et le message de refus nomme le droit qui manque.

Neuf droits commandent l'accès aux points d'entrée de cette API. Chacun ouvre au moins un point d'entrée, et le formulaire de création n'en propose pas d'autre.

DroitCe qu'il ouvre
mint:batchenvoyer un lot de produits, et lire l'avancement d'un lot
sellout:writedéclarer une vente au client final
dispatch:writerattacher chaque unité préparée par votre logisticien à sa commande B2B (rattacher chaque unité à sa commande)
catalog:readlire vos modèles, leur score de complétude et leur passeport brouillon
catalog:writecréer ou compléter des modèles, des lots et des passeports brouillons
passport:readlire le passeport publié d'un produit, d'un modèle ou d'un lot, avec sa preuve et sa signature, en un appel
scans:writeenregistrer le scan d'un de vos visiteurs
nfc:verifyvérifier la lecture d'une puce pour un de vos visiteurs, ou lire un reçu de vérification
webhooks:readlister vos abonnements, et en lire un seul
webhooks:writecréer, modifier et supprimer un abonnement
claim_codes:issueémettre les codes d'achat de vos pièces, chacun montré une fois, et lire leur état (émettre les codes d'achat)

Cochez uniquement ceux que votre intégration utilise réellement.

#Une clef pour plusieurs marques : la clef revendeur

Une clef appartient à une marque, et elle agit pour cette marque seulement.

Un revendeur sous contrat peut demander une clef revendeur. Elle agit pour sa propre marque et pour chacune des marques clientes rattachées à son contrat, sur tous les points d'entrée : catalogue, offre, codes à imprimer, affichage du passeport, frappe, déclaration de vente et webhooks. Vous n'avez pas besoin d'une clé par marque cliente. Une marque hors de votre contrat, ou un code qui ne nomme aucune marque, reçoit le même 403. Le détail est dans Remplir le catalogue par l'API et dans Afficher le passeport dans votre page.

Avec votre clé revendeur, vous frappez pour une marque cliente en mettant son code public dans le brand_code de chaque ligne de POST /v1/partner/mint/batch, un lot par marque. La vente et les webhooks prennent aussi un brand_code. Sans lui, la clé agit pour votre propre marque. L'offre et le forfait appliqués sont ceux de la marque cliente ; l'accès à l'API vient de votre offre de revendeur.

#Les trois plafonds

Trois compteurs différents peuvent refuser un appel. Ils ne se ressemblent pas et ils ne se lisent pas au même endroit. Traitez-les séparément.

#Le débit, en appels par minute

Nous comptons vos appels sur une fenêtre fixe de 60 secondes. Ce plafond s'applique aux vingt-deux points d'entrée, y compris la lecture du statut d'un lot et la suppression d'un abonnement.

Deux compteurs tournent en même temps : un pour votre clef, un pour la somme de toutes les clefs de votre marque. Le plafond est le même des deux côtés.

Votre plafond vient d'une valeur posée sur votre compte, ou à défaut de votre offre. Quand aucune des deux n'est définie, vous disposez de 120 appels par fenêtre. Ne devinez pas cette valeur : vous la lisez sur chaque réponse.

Toute réponse qui passe le plafond porte les quatre en-têtes suivants.

En-têteCe qu'il contient
X-RateLimit-Limitle plafond applicable, en appels par fenêtre
X-RateLimit-Remainingce qu'il vous reste dans la fenêtre en cours
X-RateLimit-Resetl'horodatage, en secondes depuis 1970, où la fenêtre repart
X-RateLimit-Scopekey ou brand, selon celui des deux compteurs qui est le plus contraignant

Ces en-têtes décrivent toujours le compteur le plus serré des deux. Pilotez votre cadence dessus, et ralentissez avant d'atteindre zéro.

Un dépassement renvoie 429 avec les mêmes en-têtes, plus Retry-After. Retry-After compte les secondes qui restent dans la fenêtre en cours, et vaut au minimum 1. Respectez-le. X-RateLimit-Scope vous dit lequel des deux compteurs a refusé, ce qui évite de chercher du côté de la clef quand c'est le total de la marque qui est plein.

Un dernier cas, rare : si le service qui tient ces compteurs est momentanément indisponible, les vingt-deux points d'entrée répondent 503. Un 503 signifie que l'appel n'a rien fait du tout. Réessayez plus tard.

#Le quota quotidien de la clef

Chaque clef peut porter un quota quotidien. Une clef sans quota est illimitée de ce côté. Le compteur repart de zéro au passage de minuit en temps universel. Votre fuseau horaire n'entre pas en compte.

Ce quota se compte par ligne envoyée.

  • Un lot de 100 lignes consomme 100 unités.
  • Une déclaration de vente consomme 1 unité.
  • Une écriture du catalogue qui crée ou modifie quelque chose consomme 1 unité.
  • Les autres points d'entrée ne consomment rien : les cinq points d'entrée d'abonnement aux notifications, la lecture de l'avancement d'un lot, les lectures du catalogue et les six points d'entrée de l'affichage du passeport.

Un dépassement renvoie 429 avec trois en-têtes qui lui sont propres.

En-têteCe qu'il contient
X-Quota-Limitle quota quotidien de la clef
X-Quota-Remainingce qu'il reste pour aujourd'hui
X-Quota-Resetla date de la dernière remise à zéro du compteur

La réponse porte en plus les quatre en-têtes X-RateLimit-* du contrôle de débit, que l'appel venait de passer avant d'être arrêté par le quota.

#Les pièces de votre offre

Toute offre vendue compte vos pièces par année civile, en temps universel. Une pièce est un exemplaire de produit créé. Votre offre comprend 6 000 pièces par an. Chaque pièce au-delà est facturée à la pièce. Au-delà de 1 000 000 de pièces dans l'année, le prix se fixe sur devis. Aucune pièce n'est refusée pour un volume, même au-delà de 1 000 000. Cela vaut pour une marque sur l'offre Conformité + Identité : sur l'offre Conformité, une marque ne crée aucune pièce, voir Conformité, ou Conformité + Identité. Seul le compte d'essai garde un plafond mensuel : 10 produits par période de facturation. Votre offre décide aussi si l'accès API vous est ouvert, et si les abonnements aux notifications vous sont ouverts.

Trois refus en 403 en découlent, tous porteurs d'un code lisible par votre programme.

Votre offre ne comprend pas l'accès API :

JSON
{
  "detail": {
    "code": "FEATURE_NOT_AVAILABLE",
    "feature": "api_access"
  }
}

Votre offre ne comprend pas les abonnements aux notifications :

JSON
{
  "detail": {
    "code": "FEATURE_NOT_AVAILABLE",
    "feature": "webhooks"
  }
}

Ce refus-là ne touche que la création et la modification d'un abonnement. Vous gardez la lecture et la suppression quelle que soit votre offre. Vous gardez aussi l'extinction d'un abonnement, à une condition : envoyez is_active à faux et rien d'autre. Dès qu'un second champ accompagne cette valeur, l'appel compte comme une modification et le refus s'applique.

Sur un compte d'essai, vous avez atteint les produits de votre période de facturation :

JSON
{
  "detail": {
    "code": "QUOTA_EXCEEDED",
    "resource": "products",
    "current": 8,
    "additional": 5,
    "max": 10,
    "period": "monthly"
  }
}

Celui-ci se lit ainsi : vous avez déjà créé 8 produits sur la période, vous en demandez 5 de plus, le maximum est de 10. Découpez votre lot, attendez la période suivante ou souscrivez une offre. Une offre vendue ne rend jamais ce refus pour des pièces.

#Rejouer un appel sans doubler son effet

L'envoi d'un lot accepte un en-tête Idempotency-Key. Cet en-tête porte une clef d'idempotence, c'est-à-dire une valeur qui garantit qu'un même envoi renvoyé deux fois ne produit qu'un seul traitement. Vous en choisissez la valeur, et vous la gardez le temps de vos tentatives.

HTTP
Idempotency-Key: lot-exemple-0001

Cet en-tête répond au cas où vous n'obtenez pas de réponse : coupure réseau, délai dépassé, redémarrage de votre côté. Vous ne savez pas si le lot est parti. Renvoyez la même requête avec la même valeur, et vous obtenez la réponse du premier appel sans qu'un second lot parte en traitement.

Trois comportements à connaître.

  • Même clef d'idempotence, même lot : vous récupérez la réponse du premier appel. Nous ne lançons pas un second traitement.
  • Même clef d'idempotence, lot différent : la réponse est 409. Nous ne vous rendons pas la réponse du premier appel, parce qu'elle ne décrit pas ce que vous venez d'envoyer.
  • Même clef d'idempotence pendant que le premier appel est encore en cours de traitement : la réponse est également 409. Attendez la fin du premier appel, puis réessayez.

Nous gardons une valeur 24 heures. Passé ce délai, la même valeur redevient une requête neuve, et un renvoi enverrait un second lot en traitement. N'utilisez donc jamais une valeur fixe : tirez une valeur nouvelle par lot, et gardez-la le temps des tentatives de ce lot.

La comparaison entre deux lots porte sur leur contenu une fois normalisé. L'ordre des lignes, l'ordre des colonnes, le format choisi entre CSV et JSON et les cellules laissées vides ne changent rien : nous reconnaissons deux envois du même contenu comme identiques.

Un renvoi qui rend la réponse mise en cache consomme quand même un appel sur votre plafond de débit. Il ne consomme pas votre quota quotidien, et ne compte aucune pièce.

#Pagination

Un seul point d'entrée de cette API rend une liste : GET /v1/partner/webhooks.

ParamètreTypeValeur par défautDescription
skipentier0nombre d'éléments à sauter, à partir de 0
limitentier20nombre d'éléments à rendre, entre 1 et 100

La réponse contient deux champs : items, la page demandée, et total, le nombre total d'abonnements de votre marque. Vous parcourez donc la liste en augmentant skip de la valeur de limit jusqu'à couvrir total.

Vous recevez les abonnements du plus récent au plus ancien.

#Ce qu'il faut retenir avant d'ouvrir la référence

  • L'adresse est https://api.sealtrust.io, et la forme à utiliser est /v1.
  • La clef part dans Authorization: Bearer, et nulle part ailleurs.
  • Le secret ne s'affiche qu'une fois. Une clef expire toujours.
  • Un 401 parle de la clef elle-même. Un 403 parle d'un droit, d'un statut, ou de ce que votre offre autorise.
  • Un 429 vient soit du débit, soit du quota quotidien. Retry-After désigne le débit, X-Quota-Limit désigne le quota quotidien.
  • Un 503 vient du service qui tient les compteurs de débit, et signifie que l'appel n'a rien fait.
  • Le suivi d'un lot répond finished sur un succès complet comme sur un succès partiel : lisez success_count et error_count.
  • Une requête de lot renvoyée après une coupure doit porter la même Idempotency-Key que la première tentative.

Chaque point d'entrée a sa propre page, avec ses paramètres, sa réponse réelle et son tableau d'erreurs complet. Vous les retrouvez dans la barre latérale, rangés par tâche : « Créer des produits », « Déclarer une vente », « Recevoir les événements ».

La page Erreurs rassemble les codes communs à toute l'API.

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