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
- Ce que cette API fait
- Ce qui se fait dans la console seulement
- Le contrat OpenAPI
- L'adresse de base et le préfixe /v1
- Authentifier un appel
- Obtenir une clef
- Révoquer une clef
- Les refus d'authentification
- Votre premier appel
- Les droits attachés à une clef
- Une clef pour plusieurs marques : la clef revendeur
- Les trois plafonds
- Le débit, en appels par minute
- Le quota quotidien de la clef
- Les pièces de votre offre
- Rejouer un appel sans doubler son effet
- Pagination
- Ce qu'il faut retenir avant d'ouvrir la référence
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.
| Usage | Points d'entrée |
|---|---|
| Créer des produits en lot, suivre l'avancement du traitement, et lire les pièces créées | 3 |
| Déclarer une vente au client final | 1 |
| Gérer vos abonnements aux notifications | 5 |
| Préremplir votre catalogue : modèles, lots, passeports brouillons, score de complétude | 7 |
| Afficher le passeport dans votre propre page : passeport, preuve et signature en un appel, scans et lectures NFC de vos visiteurs | 6 |
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.
| Geste | Où, dans la console |
|---|---|
| Créer une marque cliente | Vos marques clientes |
| Inviter une personne dans l'équipe d'une marque | L'équipe et les rôles |
| Créer ou révoquer une clef d'API, y compris la clef d'une marque cliente | Clés d'API et webhooks |
| Déclarer les adresses de votre page, la page qui affiche un passeport et l'envoi des scans vers elle | Clés d'API et webhooks |
| Poser le logo et les couleurs, masquer notre mention | La marque et son apparence |
| Ajouter et faire vérifier un domaine personnalisé | Le domaine personnalisé |
| Lire le relevé d'usage mensuel de vos marques clientes | Le 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.
POST https://api.sealtrust.io/v1/partner/mint/batch
POST https://api.sealtrust.io/partner/mint/batchUtilisez 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.
Authorization: Bearer votre_clefC'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 montrentst_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
| Code | Ce qui s'est passé | Que faire |
|---|---|---|
| 401 | l'en-tête Authorization est absent | ajoutez-le, la réponse porte aussi WWW-Authenticate: Bearer |
| 401 | l'en-tête ne commence pas par Bearer suivi d'un espace | corrigez la forme de l'en-tête |
| 401 | la clef est mal formée ou inconnue | renvoyez le secret complet tel que la console l'a affiché, sans espace ni retour à la ligne |
| 403 | la clef a été révoquée | créez une nouvelle clef dans la console |
| 403 | la clef a atteint sa date d'expiration | créez une nouvelle clef, l'ancienne ne redeviendra jamais valide |
| 403 | la clef n'a pas le droit requis par ce point d'entrée | le 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"import { SealTrustClient } from "@sealtrust-io/sdk";
const client = new SealTrustClient({
apiKey: "st_live_0000000000000000000000000000000000000000000000",
});
const page = await client.webhooks.list();
console.log(page.total);
console.log(page.items);import requests
response = requests.get(
"https://api.sealtrust.io/v1/partner/webhooks",
headers={
"Authorization": "Bearer st_live_0000000000000000000000000000000000000000000000"
},
timeout=30,
)
print(response.status_code)
print(response.json())Réponse, code HTTP 200, pour une marque qui n'a encore aucun abonnement :
{
"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.
| Droit | Ce qu'il ouvre |
|---|---|
mint:batch | envoyer un lot de produits, et lire l'avancement d'un lot |
sellout:write | déclarer une vente au client final |
dispatch:write | rattacher chaque unité préparée par votre logisticien à sa commande B2B (rattacher chaque unité à sa commande) |
catalog:read | lire vos modèles, leur score de complétude et leur passeport brouillon |
catalog:write | créer ou compléter des modèles, des lots et des passeports brouillons |
passport:read | lire le passeport publié d'un produit, d'un modèle ou d'un lot, avec sa preuve et sa signature, en un appel |
scans:write | enregistrer le scan d'un de vos visiteurs |
nfc:verify | vérifier la lecture d'une puce pour un de vos visiteurs, ou lire un reçu de vérification |
webhooks:read | lister vos abonnements, et en lire un seul |
webhooks:write | cré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ête | Ce qu'il contient |
|---|---|
X-RateLimit-Limit | le plafond applicable, en appels par fenêtre |
X-RateLimit-Remaining | ce qu'il vous reste dans la fenêtre en cours |
X-RateLimit-Reset | l'horodatage, en secondes depuis 1970, où la fenêtre repart |
X-RateLimit-Scope | key 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ête | Ce qu'il contient |
|---|---|
X-Quota-Limit | le quota quotidien de la clef |
X-Quota-Remaining | ce qu'il reste pour aujourd'hui |
X-Quota-Reset | la 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 :
{
"detail": {
"code": "FEATURE_NOT_AVAILABLE",
"feature": "api_access"
}
}Votre offre ne comprend pas les abonnements aux notifications :
{
"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 :
{
"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.
Idempotency-Key: lot-exemple-0001Cet 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ètre | Type | Valeur par défaut | Description |
|---|---|---|---|
skip | entier | 0 | nombre d'éléments à sauter, à partir de 0 |
limit | entier | 20 | nombre 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-Afterdésigne le débit,X-Quota-Limitdé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
finishedsur un succès complet comme sur un succès partiel : lisezsuccess_counteterror_count. - Une requête de lot renvoyée après une coupure doit porter la même
Idempotency-Keyque 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 ».
- POST
/partner /mint /batch - GET
/partner /mint /batch /status /{job_id} - POST
/partner /sellout - POST
/partner /webhooks - GET
/partner /webhooks - GET
/partner /webhooks /{webhook_id} - PUT
/partner /webhooks /{webhook_id} - DELETE
/partner /webhooks /{webhook_id}
La page Erreurs rassemble les codes communs à toute l'API.
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.