# GET /passport/01/{gtin}/10/{lot}/proof

Fetch the public proofs of a batch's passport: content hash, seal, anchoring of the document on Base without any minting, state of the signed credential. Public endpoint.

Source: https://docs.sealtrust.io/en/reference/get-passport-gtin-lot-proof/

---

You fetch the public proofs of a production batch's passport. When you leave
this page, you will know how to request these proofs, how to check by yourself
that the batch's version is written on chain, and why no minting was needed.

Full address:

```http
GET https://api.sealtrust.io/v1/passport/01/{gtin}/10/{lot}/proof
```

> [!INFO] A batch is dated without minting anything
> Every published version of a passport is sealed, then added to a Merkle tree
> whose root is written on Base by a periodic sweep. That sweep takes every
> sealed version, whatever it is attached to. A batch's passport is therefore
> dated on chain like the others, without any token being created for the
> batch or for its items.

## Authorization

None, public endpoint. The response is the same for everyone.

## Rate limit

600 calls per window of 60 seconds, counted per calling IP address, shared by
every read (`GET`) whose address starts with `/passport`.

## Path and query parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `gtin` | `string` | yes | The GTIN of the batch's model. Its check digit is verified. |
| `lot` | `string` | yes | The lot number, compared exactly, case included. |

This endpoint has no query parameter.

## Request body

None. This request has no body.

## Example request

:::onglets
```bash title="curl"
curl -i "https://api.sealtrust.io/v1/passport/01/03701234567891/10/LOT-26A/proof"
```
```typescript
const response = await fetch(
  "https://api.sealtrust.io/v1/passport/01/03701234567891/10/LOT-26A/proof",
);
const proofs = await response.json();
console.log(proofs.level, proofs.batch_code, proofs.passport_anchor);
```
```python
import requests

response = requests.get(
    "https://api.sealtrust.io/v1/passport/01/03701234567891/10/LOT-26A/proof",
    timeout=30,
)
proofs = response.json()
print(proofs["level"], proofs["batch_code"], proofs.get("passport_anchor"))
```
:::

## Example response

HTTP code `200`, for a version already anchored.

```json
{
  "passport_version": 2,
  "data_hash": "9f2c1e7d4b8a6f0e3d5c2b1a9e8f7d6c5b4a3f2e1d0c9b8a7f6e5d4c3b2a1f0e",
  "passport_anchor": {
    "type": "passport_anchor",
    "chain": "base",
    "chain_id": 8453,
    "tx_hash": "0x5e1f0c2d3b4a59687766554433221100ffeeddccbbaa99887766554433221100",
    "merkle_root": "0x0d1c2b3a49586776655443322110ffeeddccbbaa998877665544332211000f1e",
    "leaf": "0x7a6b5c4d3e2f1a0b9c8d7e6f5a4b3c2d1e0f9a8b7c6d5e4f3a2b1c0d9e8f7a6b",
    "leaf_index": 3,
    "proof": ["0x1122334455667788990011223344556677889900112233445566778899001122"],
    "block_timestamp": "2026-09-26T09:00:02+00:00",
    "passport_version": 2,
    "data_hash_matches": true,
    "anchored": true,
    "proves": "content_existed_at_or_before_tx"
  },
  "seal": {"sealed": true, "linked": true, "chain_link_match": true},
  "vc": {"issued": false},
  "level": "batch",
  "gtin": "03701234567891",
  "batch_code": "LOT-26A"
}
```

Every value in this example is fictitious, and the real response carries other
fields in `passport_anchor` and `seal`, described on
[`GET /passport/01/{gtin}/proof`](/en/reference/get-passport-gtin-proof/).

Two blocks are absent, and their absence is the right answer: `anchor`, which
dates an item, and `verifications`, which counts the reads of a physical label.
A batch is neither. As long as the version has not been taken by the sweep,
`passport_anchor` is absent too, and `seal` is enough to make any rewrite
visible in the meantime.

### Verifying the proof yourself

The leaf is `keccak256(abi.encode(uint256 passportId, uint256
passportVersion, bytes32 dataHash))`, where `passportId` is the `id` field of
[`GET /passport/01/{gtin}/10/{lot}`](/en/reference/get-passport-gtin-lot/).
Walking up from the leaf with each node of `proof`, two by two and in
ascending byte order, you get back `merkle_root`. The detail is on
[Trust and proofs](/en/confiance-et-preuves/).

## Errors

| Code | Condition | What to do |
| --- | --- | --- |
| 400 | The GTIN check digit does not match. | Copy the GTIN again from the barcode. |
| 404 | No published passport for this batch, a batch of another brand than the one of the called domain, or a batch of another brand than the one that publishes the model passport of this GTIN. | Check the lot number, case included, and the publication in the console. |
| 429 | More than 600 calls in 60 seconds from the same IP address. | Wait the number of seconds given by `Retry-After`. |

## See also

- [`GET /passport/01/{gtin}/10/{lot}`](/en/reference/get-passport-gtin-lot/),
  the content of the batch's passport.
- [Trust and proofs](/en/confiance-et-preuves/),
  what each proof establishes and how to cross-check it.
