API Reference
A small JSON API wraps the Clarity reads so you can integrate verification without any Clarity serialization knowledge. Every endpoint sends Access-Control-Allow-Origin: *, so it can be called straight from a browser.
Base URL: https://thesis-lock.vercel.app
GET /api/verify/<hash>
Verify a single 64-character hex hash. Append ?owner=<principal> to also check owner-keyed batch anchors.
curl -s https://thesis-lock.vercel.app/api/verify/9afe6f57ea2af60478ad37b2d44ae8ede492c4f3b7e70bcc7dfea92128585d06
# Batch anchor (include the owner principal)
curl -s "https://thesis-lock.vercel.app/api/verify/<hash>?owner=SP3QS6X01XKTYC84BHA0J567CZTAH67BJHN88FNVM"POST /api/verify
Same lookup over POST, taking a JSON body:
curl -s -X POST https://thesis-lock.vercel.app/api/verify \
-H 'Content-Type: application/json' \
-d '{"hash":"9afe6f57ea2af60478ad37b2d44ae8ede492c4f3b7e70bcc7dfea92128585d06"}'Or upload a file and let the server compute and verify its SHA-256. The file is hashed in memory and never stored; the response adds the computed hash under computedHash.
curl -s -X POST https://thesis-lock.vercel.app/api/verify \
-F 'file=@thesis.pdf' \
-F 'owner=SP3QS6X01XKTYC84BHA0J567CZTAH67BJHN88FNVM'Response schema
A found anchor returns verified: true:
{
"verified": true,
"source": "single",
"hash": "9afe6f57...",
"label": "project",
"owner": "SPMXTB2P571VMJP2ZG812P2H964S1XVTCDC8QNYX",
"stacksBlock": 8104143,
"burnBlock": 951262,
"contract": "SP3QS6X01XKTYC84BHA0J567CZTAH67BJHN88FNVM.thesislock",
"verifyUrl": "https://thesis-lock.vercel.app/v/9afe6f57..."
}Batch anchors set "source": "batch" and add a batchId. A miss returns 200 with verified: false; an invalid hash (not 64 hex characters) returns 400.
GET /api/search
Search anchored documents across all five contracts. Returns a JSON array.
| Parameter | Required | Description |
|---|---|---|
q | Yes | The search term. |
type | No | auto (default), hash, principal, or label. Auto treats 64-hex as a hash, an SP/ST string as a principal, and anything else as a label substring. |
owner | No | A principal to also check owner-keyed batch anchors when searching by hash. |
# Auto-detect (label substring search)
curl -s "https://thesis-lock.vercel.app/api/search?q=thesis"
# By hash
curl -s "https://thesis-lock.vercel.app/api/search?q=9afe6f57...585d06&type=hash"
# By wallet address
curl -s "https://thesis-lock.vercel.app/api/search?q=SP3QS6X01XKTYC84BHA0J567CZTAH67BJHN88FNVM&type=principal"Each result carries a source of single, batch, registry, proof, or group (group results also include a groupId). Responses are edge-cached for 30 seconds. A request with no q returns 400.
GET /api/badge/<hash>
Returns a shields-style SVG badge. It is green with the Stacks block number when the hash is anchored (Verified ✓ #<block>) and gray otherwise. Embed it in a README to prove a document is on chain.
| Query | Description |
|---|---|
style=rounded | Pill shape instead of flat corners. |
label=Your+Text | Custom left-hand label (default ThesisLock). |
owner=<principal> | Also check batch anchors. |
[](https://thesis-lock.vercel.app/v/<hash>)GET /api/card/<hash>
Returns a larger social sharing card image for the hash, suitable as an Open Graph preview. Accepts ?owner=<principal> for batch anchors. Visit the embed page to generate badge and card snippets for any hash or file.
GET /api/nft/<id>
Returns metadata and an SVG image for a proof NFT token id, backing the thesislock-proof contract's token URIs. An unknown id returns 404; a non-integer id returns 400.
GET /api/stats
Protocol-wide totals and recent activity (anchor counts, unique wallets, contracts deployed, first and latest anchor blocks, and a per-day series). Cached at the edge for five minutes.
curl -s https://thesis-lock.vercel.app/api/statsGET /api/health
Uptime probe returning the deployed contract identifiers and API version.
curl -s https://thesis-lock.vercel.app/api/health{
"status": "ok",
"contracts": {
"thesislock": "SP3QS6X01XKTYC84BHA0J567CZTAH67BJHN88FNVM.thesislock",
"batch": "SP3QS6X01XKTYC84BHA0J567CZTAH67BJHN88FNVM.thesislock-batch",
"registry": "SP3QS6X01XKTYC84BHA0J567CZTAH67BJHN88FNVM.thesislock-registry"
},
"version": "1.0.0"
}POST /api/webhook (experimental)
Register an https URL to be called once when a transaction confirms, instead of polling. This is best-effort and in-memory: registrations do not survive a serverless cold start or scale-out, and delivery is not retried. Do not depend on it for guaranteed notifications.
curl -s -X POST https://thesis-lock.vercel.app/api/webhook \
-H 'Content-Type: application/json' \
-d '{"url":"https://example.com/hooks/thesislock","txId":"0x<64-hex-tx-id>"}'When the transaction reaches a terminal state, ThesisLock POSTs to your URL:
{ "txId": "0x<64-hex-tx-id>", "status": "success", "blockHeight": 8104143 }- The
urlmust be a publichttpsendpoint. Loopback, private, link-local, and cloud-metadata addresses are rejected. txIdmust be a 32-byte (64-character) hex transaction id.- Confirmation checks run opportunistically when the API receives other traffic, so delivery latency depends on usage.