Method GET/certificate /{identifier}
Read a product's certificate of authenticity from its certificate number, its UID hash, its token id or its printed serial number. Public endpoint.
On this page
You are reading a product's certificate of authenticity. When you leave this page, you will know which identifier to send, how to read the certificate status, and which responses to expect when the product or the certificate does not exist.
Full address:
GET https://api.sealtrust.io/v1/certificate/{identifier}The same endpoint also answers without the /v1 prefix, at
https://api.sealtrust.io/certificate/{identifier}. Both addresses call the
same code. Use the /v1 form for a new integration.
#
None, public endpoint. Send neither an API key nor a session token.
The response carries no internal brand or product identifier. It gives the certificate number, the status, the dates, the product name, the brand name and its styling. It gives no brand number, no product number, no contract address and no owner address.
#Rate limit
60 calls per 60-second window, counted per IP address.
This counter is shared by every address that starts with /certificate, with or
without the /v1 prefix. Reading the certificate and downloading its PDF are
counted in the same counter.
Every accepted response carries three headers.
| Header | Content |
|---|---|
X-RateLimit-Limit | the limit applied over the window, here 60 |
X-RateLimit-Remaining | what is left to you in the current window |
X-RateLimit-Reset | the timestamp for the end of the window, in seconds |
A refusal returns 429 with the same three headers, X-RateLimit-Remaining at
0, and Retry-After equal to 60.
#Path and query parameters
| Name | Type | Required | Description |
|---|---|---|---|
identifier | string | yes | The product or the certificate to read. Four forms are accepted, described below. |
This endpoint has no query parameter.
#The four identifier forms
| Form | What it looks like |
|---|---|
| Certificate number | A string that starts with ST-CERT-, followed by 12 characters. It is the certificate_number field this same response returns. |
| UID hash | 0x followed by 64 hexadecimal characters, that is 66 characters in all. Case does not matter. |
| Token id | The token's whole number, written in digits. It has 77 or 78 digits. |
| Printed serial number | The 12 characters carried on the product label, the ones found in the /p/{serial} address. |
The server first looks for a certificate number. If it finds none, it looks at
the shape of the string: 0x followed by 64 hexadecimal characters is treated
as a UID hash, any other shape as a token id. As a last resort it looks for a
printed serial number.
The server strips leading and trailing spaces before the lookup, whatever the form.
The server ignores the case of the serial number and brings the characters that
are confused when read back to their canonical form before the lookup: I and
L count as 1, O counts as 0. So you still find a number copied by hand
from a label even if the person typed the letter O where the label carries the
digit 0.
#Headers
| Name | Type | Required | Description |
|---|---|---|---|
Accept | string | no | If it contains text/html, the response is a 307 redirect to the public certificate page, readable by a human. Any other value, including */* and application/json, gives the JSON described below. |
curl, requests and fetch send */* by default and therefore receive the
JSON. The redirect exists so that a certificate link shared and opened in a
browser displays the public certificate page.
#Request body
None. This request has no body.
#Example request
Reading the certificate whose number is ST-CERT-000000000000.
curl -i -H "Accept: application/json" https://api.sealtrust.io/v1/certificate/ST-CERT-000000000000const response = await fetch(
"https://api.sealtrust.io/v1/certificate/ST-CERT-000000000000",
{
method: "GET",
headers: {
Accept: "application/json",
},
},
);
console.log(response.status);
console.log(response.headers.get("X-RateLimit-Remaining"));
console.log(await response.json());import requests
response = requests.get(
"https://api.sealtrust.io/v1/certificate/ST-CERT-000000000000",
headers={
"Accept": "application/json",
},
timeout=30,
)
print(response.status_code)
print(response.headers["X-RateLimit-Remaining"])
print(response.json())The TypeScript SDK @sealtrust-io/sdk does not cover this endpoint. The example
above uses fetch, available with no dependency.
The three other identifier forms are written the same way.
# UID hash
curl -i -H "Accept: application/json" https://api.sealtrust.io/v1/certificate/0x0000000000000000000000000000000000000000000000000000000000000000
# Token id
curl -i -H "Accept: application/json" https://api.sealtrust.io/v1/certificate/10000000000000000000000000000000000000000000000000000000000000000000000000000
# Printed serial number
curl -i -H "Accept: application/json" https://api.sealtrust.io/v1/certificate/00000000ABCD#Example response
HTTP code 200.
{
"certificate_number": "ST-CERT-000000000000",
"status": "active",
"issued_at": "2026-03-04T10:22:07.415000Z",
"expires_at": null,
"issuer_name": "Exemple SAS",
"product_name": "Sac cabas modèle 1",
"brand_name": "Exemple SAS",
"brand_logo_url": "https://exemple-sas.test/logo.svg",
"brand_primary_color": "#1F2937",
"brand_hide_powered_by": false,
"custom_fields": {
"atelier": "Atelier 3",
"matiere": "cuir pleine fleur"
}
}The response has eleven fields and nothing else.
| Field | Type | Description |
|---|---|---|
certificate_number | string | The number of the certificate. It is the value to reuse as identifier to find this certificate directly. |
status | string | The status of the certificate. See below. |
issued_at | string | Issue date and time, in universal time, in ISO 8601 format. |
expires_at | string or null | End of validity date. No certificate issued by the platform carries one today, the value is always null. Do not build your integration on an end date. |
issuer_name | string or null | The name of the brand that issued the certificate. The server computes this field at read time and always puts the brand name in it. null when the certificate is attached to no brand. |
product_name | string or null | The name of the product covered by the certificate. |
brand_name | string or null | The name of the issuing brand. |
brand_logo_url | string or null | The address of the brand logo, to display the certificate in the brand's colors. |
brand_primary_color | string or null | The primary color of the brand. |
brand_hide_powered_by | boolean | true when the brand's plan includes white labeling. The certificate page then hides the SealTrust mention. The default value is false, so an absent field means the mention stays displayed. |
custom_fields | object or null | The free fields the brand filled in when issuing the certificate. null when it filled in none. The content is specific to each brand, no key is imposed. |
#How to read status
The server computes the status at read time. The value stored in the database is not copied as is.
status is either active or revoked.
- A revoked certificate is returned as
revokedforever. Revocation is a deliberate act and it prevails over every other rule. No endpoint returns a revoked certificate in theactivestatus. - Every other certificate is returned as
active.
The vocabulary of the API contains a third value, expired. The server computes
it at read time from expires_at. Since no certificate carries an end date
today, the API does not return it. Accept it in your code to stay robust if it
appears one day, and build no business rule on its presence.
#Redirect to the readable page
If your request announces text/html in the Accept header, the response is a
307 whose Location header points to the public certificate page. The server
returns no JSON body in that case.
#Errors
The body of an error response carries a detail field.
| Code | Condition | What to do |
|---|---|---|
| 404 | The requested path matches no route, for example because the identifier contains an unencoded slash. detail is Not Found. | Encode the identifier before placing it in the address. |
| 404 | No product matches this identifier, or the matching product has been destroyed, replaced or archived. detail is Product not found. | Check the form of the identifier. A serial number is typed as it appears on the label, over 12 characters. |
| 404 | The product exists, but no certificate has ever been issued for it. detail is No certificate found for this product. | The product can be genuine without carrying a certificate. Use the product passport to display it. |
| 429 | The limit of 60 calls per 60 seconds is reached for your IP address. detail is Rate limit exceeded: 60 requests per 60s. The Retry-After header and the X-RateLimit-* family accompany the response. | Wait the number of seconds indicated by Retry-After, then try again. This counter is shared with the PDF download. |
| 500 | An unexpected error occurred while your call was being processed. detail is Internal Server Error. | Try again. If the error persists, contact support giving the time of the call. |
#See also
GET /certificate/{identifier}/download, download the certificate of authenticity as a PDF.GET /p/{serial}, translate the printed serial number into a consumer page address.GET /resolve/{identifier}, read in one call everything a product page displays.- Core concepts, tell a model, a batch and an item apart before ordering a single label.
Was this page helpful?
Your answer opens a pre-filled email in your mail app, addressed to contact@sealtrust.io. You read it over before sending it.