Méthode GET/qr /verify
Vérifier un article à partir des paramètres signés portés par une adresse de vérification de l'ancienne forme. Point d'entrée public, sans clef d'API.
Sur cette page
Vous obtenez un verdict d'authenticité pour un article, à partir des paramètres signés d'une adresse de vérification, sans aucune clef d'API.
L'adresse complète est https://api.sealtrust.io/v1/qr/verify. La même route
existe sans le préfixe /v1, et c'est la forme /v1 qui est recommandée pour
une nouvelle intégration.
Ce point d'entrée répond 200 même quand le verdict est négatif. Un QR falsifié,
un QR trop ancien, un article pas encore frappé : dans les trois cas la réponse
est un 200 dont le champ valid vaut false. Les codes 4xx et 5xx sont
réservés aux cas où aucun verdict ne peut être rendu.
#Autorisation
Aucune, point d'entrée public. Il n'attend ni clef d'API, ni cookie de session,
ni en-tête Authorization.
Appelez-le depuis votre serveur. Notre politique de partage entre origines
n'autorise que le site public et la console SealTrust. Depuis une page web
hébergée sur un autre domaine, le navigateur bloque la réponse, et l'en-tête
X-RateLimit-Remaining n'est de toute façon jamais exposé à un script de page.
Ce qui fait foi ici, c'est la valeur s. C'est la signature que nous avons
apposée en produisant l'adresse de vérification. Sans elle, ou avec une valeur
modifiée, le verdict est négatif.
#Plafond d'appels
30 appels par fenêtre de 60 secondes, comptés par adresse IP appelante. Le
plafond est partagé par toutes les adresses qui commencent par /qr, et il
s'applique aussi bien à /qr/verify qu'à /v1/qr/verify.
Les réponses portent les en-têtes X-RateLimit-Limit, X-RateLimit-Remaining
et X-RateLimit-Reset, ce dernier donnant l'heure de remise à zéro en secondes
depuis le 1er janvier 1970. Un dépassement renvoie 429 avec en plus
Retry-After, en secondes.
Ne faites pas dépendre votre code de la présence de ces en-têtes : lisez-les s'ils sont là, et continuez s'ils manquent.
Ce point d'entrée ne consomme aucun quota de votre offre.
#Paramètres de chemin et de requête
Ce point d'entrée n'a aucun paramètre de chemin.
| Nom | Type | Obligatoire | Description |
|---|---|---|---|
u | string | oui | L'empreinte de l'article : 0x suivi de 64 caractères hexadécimaux. Les espaces de bord sont retirés, la casse n'a pas d'importance, et le préfixe 0x est ajouté s'il manque. |
ts | integer | oui | L'horodatage inscrit dans l'adresse au moment de sa production, en secondes depuis le 1er janvier 1970. |
s | string | oui | La signature, telle qu'elle figure dans l'adresse. |
t | string | non | L'identifiant du jeton. Les adresses anciennes l'omettent. Le serveur retrouve de toute façon l'identifiant réel à partir de u, et c'est celui-là qu'il renvoie. |
c | string | non | La référence courte du contrat portée par l'adresse. Ce point d'entrée l'accepte et ne la lit jamais. La présence ou l'absence de c ne change rien à la réponse. |
src | string | non | Présent dans les adresses de l'ancienne forme, avec la valeur qr. Ce point d'entrée ne le déclare pas et n'en tient aucun compte. |
latitude | number | non | Latitude transmise par l'appareil qui scanne, entre -90 et 90. Arrondie à deux décimales, soit des cellules d'environ 1,1 km, avant tout enregistrement. La position fine n'existe à aucun moment chez nous. |
longitude | number | non | Longitude transmise par l'appareil qui scanne, entre -180 et 180. Arrondie de la même façon. |
latitude et longitude vont par paire. Si vous n'en envoyez qu'une seule,
elle est écartée et le scan est enregistré sans coordonnées.
La réponse ne renvoie jamais de coordonnées : au mieux un libellé de zone. Quand
vous n'envoyez pas de coordonnées, la ville et le pays de ce libellé sont
déduits de l'adresse IP appelante, par une base de correspondance lue chez nous.
Votre adresse IP n'est envoyée à aucun service extérieur. Si la position du
scan compte pour vous, envoyez latitude et longitude. Sinon, sachez que la
zone enregistrée sera celle de la machine qui appelle.
#Corps de la requête
Aucun. C'est une requête GET, tout passe par les paramètres de requête.
#Requête d'exemple
curl -i -G https://api.sealtrust.io/v1/qr/verify \
--data-urlencode "u=0x0000000000000000000000000000000000000000000000000000000000000000" \
--data-urlencode "t=1024" \
--data-urlencode "ts=1755000000" \
--data-urlencode "c=0x00000000" \
--data-urlencode "s=0000000000000000000000000000000000000000000000000000000000000000"// À exécuter sur votre serveur, avec Node 18 ou plus récent.
// Depuis une page web d'un autre domaine, le navigateur bloque la réponse.
const parametres = new URLSearchParams({
u: "0x0000000000000000000000000000000000000000000000000000000000000000",
t: "1024",
ts: "1755000000",
c: "0x00000000",
s: "0000000000000000000000000000000000000000000000000000000000000000",
});
const response = await fetch(
`https://api.sealtrust.io/v1/qr/verify?${parametres.toString()}`,
);
console.log(response.status);
// Cet en-tête n'est lisible que depuis un appel serveur, et il peut manquer.
console.log(response.headers.get("X-RateLimit-Remaining"));
console.log(await response.json());import requests
response = requests.get(
"https://api.sealtrust.io/v1/qr/verify",
params={
"u": "0x0000000000000000000000000000000000000000000000000000000000000000",
"t": "1024",
"ts": "1755000000",
"c": "0x00000000",
"s": "0000000000000000000000000000000000000000000000000000000000000000",
},
timeout=30,
)
print(response.status_code)
# Cet en-tête peut manquer, donc lisez-le sans exiger sa présence.
print(response.headers.get("X-RateLimit-Remaining"))
print(response.json())#Réponse d'exemple
Code HTTP 200OK
Code HTTP 200, verdict positif.
{
"valid": true,
"message": "Authentic product: QR code and blockchain verified.",
"uid_hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"token_id": "1024",
"product_name": "Sac de voyage Exemple SAS",
"brand_name": "Exemple SAS",
"image_url": null,
"contract_address": "0x0000000000000000000000000000000000000000",
"scan_area": "Lyon, FR"
}Ici l'article n'a pas d'image de couverture, donc image_url vaut null.
Quand il en a une, le champ porte son adresse publique. Le champ scan_area
est renseigné parce que l'appel a pu être situé. Il vaut null sinon.
Code HTTP 200 également quand le verdict est négatif, et la réponse n'a pas la même forme selon le verdict.
Trois verdicts négatifs sont rendus avant toute lecture sur la chaîne :
signature refusée, adresse trop ancienne, article pas encore frappé. Ces trois
réponses ne portent que uid_hash.
{
"valid": false,
"message": "Invalid QR code signature. This QR code may be tampered with.",
"uid_hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"token_id": null,
"product_name": null,
"brand_name": null,
"image_url": null,
"contract_address": null,
"scan_area": null
}Le quatrième verdict négatif est rendu après la lecture sur la chaîne, quand
l'empreinte lue ne correspond pas. Cette réponse décrit l'article, comme le
verdict positif. Seul scan_area reste null, parce que la zone n'est
calculée que sur un verdict positif.
{
"valid": false,
"message": "Invalid product: blockchain verification failed.",
"uid_hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"token_id": "1024",
"product_name": "Sac de voyage Exemple SAS",
"brand_name": "Exemple SAS",
"image_url": null,
"contract_address": "0x0000000000000000000000000000000000000000",
"scan_area": null
}Les neuf champs de la réponse.
| Champ | Type | Description |
|---|---|---|
valid | boolean | Le verdict. C'est le seul champ sur lequel construire votre logique. |
message | string | Une phrase en anglais qui explique le verdict. Fondez vos décisions sur valid, jamais sur ce texte. |
uid_hash | string ou null | L'empreinte de l'article, normalisée : minuscules, préfixe 0x. Renseignée dès que l'article a été trouvé, y compris sur un verdict négatif. |
token_id | string ou null | L'identifiant du jeton, en base 10, sous forme de chaîne. C'est celui enregistré chez nous, qui peut différer du t que vous avez envoyé. Renseigné sur un verdict positif et sur le verdict Invalid product: blockchain verification failed. |
product_name | string ou null | Le nom de l'article. Même règle de présence que token_id. |
brand_name | string ou null | Le nom de la marque propriétaire. Renvoyé dans les mêmes cas que token_id, et null quand l'article n'est rattaché à aucune marque. |
image_url | string ou null | L'adresse publique de l'image de couverture. null quand l'article et son modèle n'en ont aucune. |
contract_address | string ou null | L'adresse du contrat qui porte ce jeton, en minuscules. Même règle de présence que token_id. |
scan_area | string ou null | La zone du scan. Ville, PP quand la ville et le code pays à deux lettres sont connus tous les deux, par exemple Lyon, FR. Quand une seule partie est connue, le champ ne porte que celle-là, Lyon ou FR. null quand aucune des deux n'est connue. Renseigné seulement sur un verdict positif. Jamais de coordonnées, jamais d'adresse postale. |
#Les six verdicts possibles
valid | message | Ce que cela veut dire |
|---|---|---|
true | Authentic product: QR code and blockchain verified. | La signature est reconnue et l'empreinte enregistrée sur la chaîne correspond. |
false | Invalid product: blockchain verification failed. | La signature est reconnue, mais l'empreinte lue sur la chaîne ne correspond pas. |
false | Invalid QR code signature. This QR code may be tampered with. | La signature ne correspond pas à celle que nous attendons pour cet article. |
false | QR code has expired. Please request a new QR code. | L'horodatage ts s'écarte de plus de 30 jours de l'heure courante, en avance comme en retard. Produisez une nouvelle adresse de vérification depuis votre console. |
false | This product has not been minted yet. | L'article existe chez nous, sa frappe n'a jamais été envoyée. Rappeler plus tard ne changera rien. |
false | Mint submitted, waiting for on-chain confirmation. | La frappe a été envoyée et attend sa confirmation. Rappelez dans quelques minutes. |
#Erreurs
| Code | Condition | Que faire |
|---|---|---|
| 404 | Aucun article vivant ne porte cette empreinte. Message Product not found for this QR code. L'article a été détruit, ou retiré du catalogue. | Vérifiez la valeur de u. Si l'article a été détruit ou retiré du catalogue, ce code est définitif. |
| 404 | La chaîne ne connaît pas ce jeton. Message Unknown product: this token_id does not exist. | Rien à corriger côté appel. Contactez la marque : l'article est enregistré chez nous avec un identifiant de jeton que le contrat ne porte pas. |
| 422 | Un paramètre obligatoire manque (u, ts ou s), ts n'est pas un entier, ou latitude et longitude sortent de leurs bornes. | Le corps de la réponse liste les paramètres fautifs et le motif de chaque refus. Corrigez et rappelez. |
| 429 | Plus de 30 appels en 60 secondes depuis la même adresse IP. Message Rate limit exceeded: 30 requests per 60s. | Attendez le nombre de secondes indiqué par Retry-After. Répartissez vos appels au lieu de les envoyer en rafale. |
| 500 | Erreur inattendue du serveur. Corps figé {"detail": "Internal Server Error"}. | Réessayez. L'en-tête X-Request-Id identifie l'appel ; transmettez-le-nous s'il se répète. |
| 503 | La lecture sur la chaîne a échoué. Message Error during blockchain verification. | Réessayez dans quelques instants. Aucun verdict n'a été rendu, et le scan n'a pas été enregistré. |
#Voir aussi
GET /p/{serial}, traduire le numéro de série imprimé en adresse de page consommateur.GET /resolve/{identifier}, lire en un appel tout ce qu'une page produit affiche.- Identification physique, QR et NFC, choisir le porteur physique et la forme exacte du lien GS1 Digital Link.
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.