# Record a file's fingerprint from your own agent or app

Your code computes the SHA-256 of the final file. It sends only that fingerprint to ClearedBadge, and you get a record ID and a Verify link. The file never leaves your machine.

```bash
python record_file.py record report.pdf
python record_file.py verify report.pdf <record_id>
```

- **Requirements:** Python 3.8+, standard library only. No account, no API key, no secret.
- **What is sent:** exactly `{"sha256":"<64 lowercase hex>"}` to `POST https://clrbadge-seven.vercel.app/record-file-hash`. That is the same public route the website's Record page uses (Private, "Enter an existing SHA-256").
- **What you get:**
  - `report.pdf.clrbadge-receipt.json`: the engine's answer, saved byte for byte. It holds `badge_id`, `hash`, `created_at`, `status`, `record_type` and `fingerprint_method`.
  - The Verify link: `https://clrbadge-web.vercel.app/verify?id=<badge_id>`.
- **Handing over:** give the recipient the unchanged file and the Verify link. They drop the file on the Verify page. The comparison runs in their browser and needs no ClearedBadge account.

## The same steps in any language

1. Compute the SHA-256 of the exact file bytes, as lowercase hex.
2. Send `POST /record-file-hash` with body `{"sha256":"…"}` and `Content-Type: text/plain`.
3. On `201`, check that the answer's `hash` equals your fingerprint. Then keep the answer as the receipt.
4. Build the Verify link from `badge_id`.

```bash
curl -s -X POST https://clrbadge-seven.vercel.app/record-file-hash \
  -H 'Content-Type: text/plain' \
  -d "{\"sha256\":\"$(sha256sum report.pdf | cut -c1-64)\"}"
```

## Rules the example follows

- **Register once,** for the final file. If you edit the file afterwards, it no longer matches; recording the new version is a new record and the user's decision.
- **Never retry automatically.** After a timeout, a dropped connection, a 5xx or an unexpected answer, a record may exist. The script reports "outcome unknown" and refuses to send again until the user decides.
- **Refusals record nothing:** `400` means an invalid fingerprint; `429` means a limit was reached; `403`/`503` means registration is paused or unavailable.

## Limits (beta)

- **This public route** allows 5 registrations per connection per hour, 20 per day, and 500 per day in total. The website's Record page counts toward the same limits. Agents that share one IP address share its limit.
- **The MCP connector** (`https://clrbadge-mcp.vercel.app/mcp`) is a separate system: an account with a small registration quota.

## What a match shows

That the compared file has exactly the bytes whose fingerprint was recorded, at the recorded time. **Not** that its content is true, who made or sent it, or that anyone received it. ClearedBadge never received the file, so it cannot say which file a fingerprint belongs to.

New records are currently not anchored on Arweave, so the recorded time is ClearedBadge's own, without an independent external timestamp.

## Try the verify step now

The PDF [`../antwerpen-in-3-tips.pdf`](../antwerpen-in-3-tips.pdf) is a real record. ChatGPT Work registered it through the website on 29 October 2026.

```bash
python record_file.py verify ../antwerpen-in-3-tips.pdf b7817930-72a6-481e-ac80-ad11729ac48e
```

The answer is `match`. Change one byte and it is `differs`. This only compares; it records nothing.
