Method GET/certificate /{identifier} /download
Download the certificate of authenticity of an item as a PDF, in your brand's colors. Public endpoint, no API key.
On this page
You get back a PDF file ready to print or to attach to a message: the certificate of authenticity of an item, in your brand's colors, in French or in English.
The full URL is
https://api.sealtrust.io/v1/certificate/{identifier}/download. The same
endpoint exists without the /v1 prefix, and the /v1 form is the recommended
one for a new integration.
On success, the response is the document itself, of type application/pdf,
served as an attachment. Write the body of the response into a file. Do not try
to read it as text.
The server builds the document on every call and stores it nowhere. Two successive calls can therefore give two different files if the state of the certificate changed in between.
#
None, public endpoint. It expects neither an API key, nor a session cookie, nor
an Authorization header. A server-to-server call is accepted.
#Rate limit
60 calls per 60 second window, counted per calling IP address. Every URL that
starts with /certificate shares this counter, and the form
/v1/certificate/{identifier}/download counts in the same counter as the form
without the prefix.
Under normal conditions, every response carries the headers
X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset, the last
one giving the reset time in seconds since January 1, 1970. Treat these three
headers as optional: read them when they are there, do not make your
integration depend on their presence. Going over returns 429 with, in addition,
Retry-After, in seconds.
This endpoint consumes no quota of your plan.
#Path and query parameters
| Name | Type | Required | Description |
|---|---|---|---|
identifier | string | yes | What designates the item or the certificate. Four forms are accepted, see the detail below. The server strips surrounding whitespace. |
lang | string | no | Language of the document: fr or en. Default value en. |
#The four forms of the identifier
The server tries the certificate number first. If that leads nowhere, it looks
at the shape of the value: 0x followed by 64 hexadecimal characters is
treated as an item hash, any other value as a token identifier. A hash is
therefore never tried as a token identifier, nor the other way around. As a
last resort, the server tries the printed serial number.
| Form | Example | Detail |
|---|---|---|
| Certificate number | ST-CERT-000000000000 | Exact comparison, case matters. This is the number your console shows on the certificate and that GET /certificate/{identifier} returns. |
| Hash of the item | 0x0000000000000000000000000000000000000000000000000000000000000000 | 0x followed by 64 hexadecimal characters. Case does not matter. |
| Token identifier | 11111111111111111111111111111111111111111111111111111111111111111111111111111 | The number carried by the token on the chain, in base 10, as is. This number is 77 to 78 digits long. Read it as text, never as an integer of your language. |
| Printed serial number | 00000000ABCD | The 12 characters printed on the label of the item. Case does not matter, and the server brings back to their canonical form the characters that are confused when read: I and L count as 1, O counts as 0. You can therefore copy a number by hand without worrying about those three letters. |
The last three forms designate an item. The server then looks for the certificate of that item: the certificate currently valid if there is one, otherwise the most recent one whatever its state.
When it resolves those three forms, the server sets aside items that were destroyed and items withdrawn from the catalog, and answers 404. The certificate number does not go through the item: it finds the certificate row directly, and the document downloads even when the item was destroyed or withdrawn from the catalog.
#The language of the document
fr and en are the two values provided for, in lowercase. A value that
starts with neither fr nor en produces a document in English.
#Request body
None. This is a GET request, everything goes through the URL.
#Example request
curl -sS -D - \
-o certificat.pdf \
"https://api.sealtrust.io/v1/certificate/ST-CERT-000000000000/download?lang=fr"import { writeFile } from "node:fs/promises";
const response = await fetch(
"https://api.sealtrust.io/v1/certificate/ST-CERT-000000000000/download?lang=fr",
);
if (!response.ok) {
throw new Error(`${response.status} ${await response.text()}`);
}
console.log(response.headers.get("Content-Type"));
console.log(response.headers.get("Content-Disposition"));
console.log(response.headers.get("X-RateLimit-Remaining"));
await writeFile("certificat.pdf", Buffer.from(await response.arrayBuffer()));import requests
response = requests.get(
"https://api.sealtrust.io/v1/certificate/ST-CERT-000000000000/download",
params={"lang": "fr"},
timeout=60,
)
response.raise_for_status()
print(response.headers["Content-Type"])
print(response.headers["Content-Disposition"])
print(response.headers["X-RateLimit-Remaining"])
with open("certificat.pdf", "wb") as fichier:
fichier.write(response.content)#Example response
HTTP code 200. The body is the PDF file.
HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Disposition: attachment; filename="certificate-ST-CERT-000000000000.pdf"
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 59
X-RateLimit-Reset: 1755000060The file name offered is always certificate- followed by the certificate
number, then .pdf. That number can differ from the identifier you sent: if
you queried the item by its serial number, the file name carries the number of
the certificate found.
#What the document contains
One A4 page. Here is what the server draws on it, from top to bottom, then the border that surrounds the whole page.
| Element | Detail |
|---|---|
| Title banner | "Certificat d'authenticité" or "Certificate of Authenticity", followed by "Émis par" and the name of your brand. The banner is painted in your secondary color. |
| Logo | The logo of your brand. The server fetches it only if its address is in https, if it answers 200 in less than 4 seconds with an image/... type, and without a redirect. An address in http, a redirect, a longer delay or an address that points to a private network leave the document without a logo, the rest is unchanged. The logo fetched is also placed at the center of the QR code. |
| Status badge | ACTIF, RÉVOQUÉ or EXPIRÉ, at the top right. The server recomputes the state at render time: a certificate recorded as active whose expiry date has passed prints as EXPIRÉ. |
| Details | Product, certificate number, issue date, then the issuing brand and the expiry date when they are filled in, then at most four of the custom fields attached to the certificate. The label printed for a custom field is the name of the field with the underscores replaced by spaces and each word capitalized: numero_lot becomes Numero Lot. The value is printed as is, converted to text. |
| Blockchain proof | The name of the network, always present, Base in production. Then the address of the contract in shortened form and the token identifier, each one only when the item carries one. |
| Verification QR code | Points to the public page of the certificate on the SealTrust site. The address is also written out in full under the box. |
| Watermark seal | Two circles, a check mark and the words AUTHENTIQUE and VÉRIFIÉ BLOCKCHAIN, drawn transparently in your primary color, at the middle of the bottom of the page. The server always draws it. |
| Footer | "Propulsé par SealTrust, authenticité vérifiée par blockchain" or "Powered by SealTrust, Blockchain-verified authenticity". If your plan includes white label, this mention is not printed and the line stays empty. The server always draws the colored banner that carries this text. |
| Border | A rounded edging in your primary color, all around the page. The server always draws it. |
The server cuts a value that is too long for its line and ends it with a continuation character. That is the case of the token identifier, which is 77 to 78 digits long. Do not copy a long value from the document, read it from the API.
The document takes up the primary color and the secondary color of your brand.
If your brand has filled in no color, the document uses #6386F1 as the
primary and #0f172a as the secondary.
The logo and the two colors are the three settings that change the look of the
document, and you set them yourself in the administration, tab Settings, then
Brand. They apply to the certificate as of the next download. Every paid plan
opens this screen. The free trial keeps it closed.
#Errors
The errors, for their part, are JSON. A document starts with %PDF. A body
that starts with { signals a refusal. Check the HTTP code before writing the
file.
| Code | Condition | What to do |
|---|---|---|
| 404 | No certificate carries this number, and no item in the catalog matches this identifier. Message Product not found. An item destroyed, replaced by a new mint or withdrawn from the catalog answers the same thing. | Check the value sent in the URL. If the item was destroyed or withdrawn from the catalog, this code is final for this identifier. The certificate number, for its part, keeps working. |
| 404 | The item exists, no certificate was ever issued for it. Message No certificate found. | Issue a certificate for this item from your console, then call again. |
| 429 | More than 60 calls in 60 seconds from the same IP address, across all /certificate URLs. Message Rate limit exceeded: 60 requests per 60s. | Wait the number of seconds given by Retry-After. Spread your calls out instead of sending them in bursts. |
| 500 | Unexpected server error. Fixed body {"detail": "Internal Server Error"}. | Try again. When the X-Request-Id header is present, it identifies the call: pass it on to us if the error repeats. |
This endpoint has no other refusal code. The lang parameter is never
rejected, and the identifier is accepted whatever its shape, even if that means
finding nothing.
#See also
GET /certificate/{identifier}, read the certificate of authenticity of an item.GET /resolve/{identifier}, read in one call everything a product page displays.- Basics, tell model, batch and 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.