README: proposed Verae chain API changes for hash lookup, receipts, metadata

Answers the developer question "how do I query my original hash, get a
receipt on submission and on lookup, see all timestamp metadata, and store
metadata or links in a timestamp". Lists the required additions to
api.veraetime.net (hash lookup, idempotent create with digest input, full
status on lookup, metadata field), recommended extras (certified retrieval
receipt, JSON errors, completion callback), spec rules for public vs
private metadata, and what the middleware can cover without API changes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Andrew Birkholz 2026-09-15 12:34:00 -06:00
commit d42aa4e455

View file

@ -156,3 +156,52 @@ Where the Zapier ↔ Verae path stands, and what is still open. Sources: this re
- Encrypted object storage and shares (`/objects*`, `/shares/*`) — mock-only today; add creates
here once the middleware contract is final.
- Anything that talks to NATS or api.veraetime.net directly.
## Proposed changes to the Verae chain API
Context: a developer asked how to query an original hash, get a receipt back from both the
original submission and later lookups, see every timestamp field and its metadata, and store
metadata (or links to it) in a blockchain timestamp. Against the live OpenAPI
(`docs/00-sources/veraetime-openapi.yaml`) none of that is possible today: lookups are by job ID
only, `POST /api/timestamp` returns just `{ jobId }`, and the request has no metadata field.
The middleware mocks all of it (`MOCK_VERAE=true`) but its live client may only call paths in
the snapshot spec.
### Required on api.veraetime.net
| Ask | Change to the Verae API | Why the chain, not the middleware |
|-----|-------------------------|-----------------------------------|
| Query by original hash | New `GET /api/hashes/{sha256}` → `{ exists, jobId, sha256, timestamp, blockIndex, certificate }`. The chain already records `dataHash` per transaction; it needs an index on it. | Only the chain can find hashes sealed by any submitter. A middleware index only knows what passed through it. |
| Receipt on original submission | Make `POST /api/timestamp` idempotent on the digest: if the hash already exists return `200 { jobId, existing: true, certificate, timestamp, blockIndex }` instead of `202`. Accept a pre-hashed input `{ sha256 }` alongside `{ data }` so clients never ship the document. | Idempotency has to live where the seal lives. Accepting a digest also stops raw data landing in blocks. |
| Receipt on lookup | Have the hash lookup and `GET /api/verify/{jobId}` return the full `StatusResponse` (certificate + block metadata). The shape exists; the lookup just needs to reuse it. | No new data, a consistent response. |
| Metadata in the timestamp | Optional `metadata` object on `TimestampRequest` with a documented size cap, stored with the transaction and returned on status, verify, and hash lookup. Add `metadataHash` as an alternative for callers who want to commit to metadata without publishing it. | Anything the seal must prove existed at that time has to be inside what the chain hashes. Everything else stays off chain. |
### Strongly recommended
- **Certified retrieval receipt** — `GET /api/receipts/{jobId}?format=json|pdf`, where the chain
seals a `document.retrieved` event referencing the original job and returns both. The
middleware mocks this; a chain-signed receipt is what makes it certified.
- **JSON error bodies everywhere** — the spec promises `{ error, code }` but the live service
returns plain text on 401 (`Unauthorized: token is missing`). Every client special-cases it.
- **Completion callback or job list** — an optional `callbackUrl` on create, or
`GET /api/jobs?since=…`. Today every consumer polls `GET /api/status/{jobId}` per job.
### Rules to write into the spec
- Public metadata on chain is immutable and readable by anyone. Private metadata never goes on
chain; only a hash commitment does.
- Define `data` as "bytes to hash" and state whether blocks retain it. The `/admin/*` examples
show blocks carrying a base64 `data` field that decodes to the sample input, which suggests
they do — that matters for privacy and should be confirmed on a live seal.
### What can be done without touching the API
The middleware can index SHA-256 → job ID at submission, store public/private metadata, and
merge both back into `/status/{jobId}` and `/hashes/{sha256}` on the live path (it already does
so in mock). That covers the developer's flow for anything submitted through Verae's own
middleware. It cannot deliver chain-wide lookup, chain-level idempotency, or a chain-signed
receipt — those are the real API asks in the table above.
This Zapier app already sends `sha256`, `publicMetadata`, and `privateMetadata` to the
middleware and exposes Find Timestamp by SHA256, Find Job Verification Details, and Get
Retrieval Receipt, so no app change is needed once either side lands.