AOTrust

Prove that a document, email, contract, AI output, source code file, or any other digital artifact existed at a specific time. Public cryptographic timestamping infrastructure for developers and AI agents: a verifiable receipt (PDR) for $0.01 via HTTP API or MCP.

$0.01 · PDR $0.10 · FreelanceShield $0.02 · evidence bundle free tier 5 / 24 h hourly cumulative anchor RFC 9162 proofs

What can be notarized?

Emails · Contracts · AI outputs
Source code · Datasets · Logs
Research notes · Financial reports · Photos
Invoices · Certificates · Recordings

The artifact itself is never uploaded - only its SHA-256 hash.

Developer quickstart

AOTrust exposes notarization through the HTTP API and MCP. A consumer web product exists as FreelanceShield (PDF certificate, $0.10/file).

  1. Compute hash - hashlib.sha256(artifact).hexdigest(). Examples by artifact type: SKILL.md.
  2. Pay & notarize - $0.01 USDC via x402 on Base (HTTP) or Base/Solana (MCP). Call notary_notarize_paid (MCP) or POST /notarize (HTTP). Free tier first: notary_free / POST /v1/shield/free (5 per 24 h per IP).
  3. Track by job_id - keep the returned job_id (UUID). Status: GET /v1/status/{job_id}; PDR: GET /v1/pdr/{job_id} or result.pdr_b64. Verify at verify.aotrust.link.
# HTTP, x402 on Base
curl -si -X POST https://api.aotrust.link/notarize \
  -H 'Content-Type: application/json' -d '{"work_hash":"<sha256 hex>"}'
# → 402 (amount=10000) → sign EIP-3009 → resend with x-payment → 200 {"pdr_b64":"…"}

Python SDK (free tier, no signup)

pip install aotrust-protocol
import asyncio, hashlib
from agent_notary import NotaryClient  # base_url WITHOUT /v1 - SDK adds it

client = NotaryClient(base_url="https://api.aotrust.link")
r = await client.shield_free(hashlib.sha256(b"my artifact").hexdigest())
print(r["job_id"])                     # keep this UUID - your handle
print((await client.get_status(r["job_id"])).status)

5 free receipts / 24 h per IP. Full example: aotrust_sdk_free.py.

Evidence bundle - $0.02 (audit-grade pack)

curl -si -X POST https://api.aotrust.link/v1/attestation/bundle \
  -H 'Content-Type: application/json' -d '{"work_hash":"<sha256 hex>"}'
# → 402 (amount=20000) → pay → 200: pdr_b64 + anchor{mode, anchor_seq, size, root, near_tx, index, path[]}
# read-only: no new PDR is created

Payment rails

x402 - Base

$0.01 USDC · live

HTTP 402 + EIP-3009. Discovery: /.well-known/x402. No account, no API key.

x402 - Solana

$0.01 USDC · live (MCP)

SVM exact scheme, spl-token transferChecked + memo. Anchor type 0x0A X402_SOLANA.

NEAR_DIRECT

dynamic ~$0.01 · frozen

Rail kept for compatibility; tool available, no mainnet usage. 0x01 NEAR_DIRECT.

Free tier

$0 · 5 / 24 h

POST /v1/shield/free or MCP notary_free. No wallet, mainnet cryptography, the same hourly cumulative NEAR anchor as a paid receipt - the paid tier only removes the quota.

Buy an evidence bundle in 3 steps

An evidence bundle is a paid, read-only receipt pack for a hash we already notarized: we return the earliest issuance, the anchor that covers it, an RFC 9162 inclusion path and a step-by-step recipe to check it yourself. $0.02 USDC on Base, no account or API key.

1) Ask for the price - POST https://api.aotrust.link/v1/attestation/bundle · body {"work_hash":"<64 hex>"} → HTTP 402 with accepts[] (amount 20000 = $0.02, payTo 0x97E9…c800, USDC 0x8335…2913, network eip155:8453)
2) Sign the EIP-3009 authorization and resend the same request with the x-payment header
3) Get JSON back: picked:"earliest", seq, payment_hash, issuance_count, first_seq, issuances[], anchor{mode,anchor_seq,size,root,near_tx,index,path} - then verify it in the browser at /transparency.html

Optional: pass seq to pin a specific issuance - we reject the request before any payment with 400 INVALID_SEQ or 400 SEQ_HASH_MISMATCH. Unknown hash → 404, nothing charged.

No wallet yet? The free tier (POST /v1/shield/free, 5 per 24 h) issues a real mainnet PDR without payment; the bundle adds the anchor proof and the earliest-issuance guarantee.

Current status (October 2026)

Production

PDR issuance · public verification · x402 on Base + Solana · hourly cumulative NEAR anchoring · anchor proof/consistency API · evidence bundle ($0.02) · signed time attestations ($0.002) · transparency log

Developer access

HTTP API · MCP (streamable-http) · agent integrations · SDK aotrust-protocol · JWKS / did:web

In development

Consumer UX polish · more catalog listings · Solana settlement checks

What is a PDR?

A PDR (Provenance Data Record) is a 239-byte cryptographic receipt that proves a specific digital artifact existed at a specific point in time. It is signed with Ed25519 (AOTrust signed message) and is a leaf in an append-only Merkle log anchored hourly to the NEAR blockchain.

size
239 bytes total
hash
SHA-256 work hash
anchor
cumulative Merkle log, hourly
signature
Ed25519 · AOTrust signature frame

MCP tools

MCP is fully operational: connect any MCP-compatible agent to https://api.aotrust.link/mcp, or use the HTTP API above.

ToolDescriptionInputsReturns
notary_quoteGet dynamic price quote(none)cost_usd_cents, cost_near_human, near_usd_rate, quote_id, quote_valid_until
notary_freeFree UNPAID PDR (no payment, no wallet; 5/day/IP)work_hashpdr_b64, job_id
notary_notarizeNEAR_DIRECT notarization (rail frozen)work_hash, tx_hash, agent_pubkeypdr_b64, job_id
notary_notarize_paidx402 USDC on Base or Solana (live; HTTP /notarize is Base-only)work_hash, agent_pubkeypdr_b64, tx_hash, payment_anchor_type
notary_verifyVerify an existing PDRpdr_b64 or work_hashstatus, issuer, timestamp, signature_valid

Complete current list: MCP tools/list or SKILL.md.

PDR format v2.3 / v2.4 (technical reference)

FieldSizeDescription
version10x03 (v2.3) or 0x04 (v2.4 bilateral)
sig_scheme10x01 = Ed25519 / AOTrust signed message
payment_anchor_type1Payment rail enum (0x00 unpaid, 0x01 NEAR_DIRECT, 0x05 X402_BASE, 0x0A X402_SOLANA, …)
timestamp8UNIX seconds, uint64 LE
issuer_id36Notary account, NUL-padded UTF-8
subject_hash32Agent public key bytes (bilateral) / account hash
payload_hash32work_hash (v0x03) or binding hash (v0x04)
merkle_root32Segment root at issuance (anchored in the cumulative log)
payment_hash32On-chain payment reference
signature64Ed25519 over AOTrust signature frame of the 175-byte payload
TOTAL239bytes

Bilateral (v0x04) details, binding-hash formula and a live test vector: specification.

Disclaimer: PDRs are cryptographic evidence of hash existence at a point in time. They are NOT legally recognized notarization, electronic signatures, or qualified timestamps under EU eIDAS or any national notary law.

How a PDR relates to the IETF leg-record model

Since October 2026 the IETF SCITT work includes individual Internet-Drafts that describe a two-party settlement as up to four signed leg records - terms, payer-observed, payee-observed, delivered - each sealed by the party that observed that fact, with the settlement state (one-sided, agreed, mismatch) derived by a verifier. These are drafts, not an RFC and not an adopted standard; the vocabulary is becoming the common one for agent-payment evidence, so here is the exact mapping.

IETF legWhat it recordsWhere it lives in a PDR
termsPrice and deliverable, sealed by the party that set themOutside the record: the published price and the x402 offer. A PDR carries only the rail in payment_anchor_type
payer-observedWhat the payer's system sent, signed by the payerCited, not signed by the payer: payment_hash (32 bytes) plus GET /v1/pdr/by-tx/{tx}
payee-observedWhat the payee's system received, signed by the payeeThis is the notary's own signature: issuer_id + signature over the 175-byte payload
deliveredDigest of what was deliveredpayload_hash = work_hash; in v0x04 the binding SHA256(work_hash ‖ sig_A ‖ pub_A)
transparency receiptProof the record was registered in a logmerkle_root + the NEAR anchor and RFC 9162 inclusion/consistency proofs

In short: a PDR is the payee-observed + delivered pair, sealed by the notary acting as the receiving party, citing the payer's transaction by hash. Two deliberate differences remain. First, the trust root is a public chain (NEAR), not an operator's transparency log: the verifier trusts the chain, not us. Second, a PDR does not derive an agreed state - in v0x03 the payer's observation is not counter-signed, and there is no refusal record. A PDR → Capsule compatibility adapter is not shipped; ask if you need one.

NEAR anchoring & independent verification

Every PDR carries the notary's Ed25519 signature. Beyond that, every work hash becomes a leaf in an append-only Merkle log (RFC 9162, Certificate Transparency model); when new receipts exist, the current root of the whole log is committed hourly to the NEAR contract notary-node.near. Your receipt stays verifiable even if this website disappears - the root lives on-chain, and consistency proofs show the log was never rewritten.

Online verification (no trust in us)

Any NEAR RPC node can read the contract: get_root({"seq": N}) returns the committed root. Compare it with your inclusion proof root (or the merkle_root inside the PDR for legacy receipts). The on-chain sequence counter counts anchor() calls; use the recorded anchor_seq as the source of truth.

Offline verification (when our servers are gone)

You keep three things, and one lives on-chain - no AOTrust server required:

  1. Your PDR, plus the verify JSON saved when the receipt was fresh (merkle_proof, merkle_index, merkle_leaf, merkle_tree_size).
  2. The on-chain root: any public NEAR RPC, get_root({"seq": N}) on notary-node.near.
  3. The standalone verifier verify_merkle_inclusion.py (zero dependencies, RFC 9162 §2.1.3):
python3 verify_merkle_inclusion.py --leaf <merkle_leaf> --proof <comma-joined> \
  --index <merkle_index> --root <merkle_root> --tree-size <merkle_tree_size>
# → VALID

Trust model: signature = who attested and when (offline, instantly). Merkle anchor = durability - no one, including us, can erase or forge the record. For bilateral receipts (v0x04) the verify API re-derives the work hash by the binding check sha256(work_hash + sig_A + agent_pubkey) == payload_hash.

Anchoring is cumulative: each anchor commits a single root over all receipts in append-only order. Anyone can verify the log only grew via RFC 9162 §2.1.4 consistency proofs - see the public transparency log.

First registration & reaffirmation

One fingerprint - one canonical first record. The first time a SHA-256 is registered it becomes the first registration for that file. Every later submission of the same bytes is a reaffirmation: a new signed record with its own timestamp, marked as such, and exempt from the per-IP free quota. A reaffirmation never replaces or outranks the first record, so an earlier proof cannot be overwritten or re-issued to someone else.

The canonical state is derived from the append-only ledger (first date, first record id, number of registrations, whether the first record is already covered by an anchor) - it is never stored as a second source of truth.

POST /v1/verify/hash

Ask the registry what it knows about a file you hold, without a receipt and without uploading anything:

curl -s -X POST https://api.aotrust.link/v1/verify/hash \
  -H 'Content-Type: application/json' \
  -d '{"work_hash":"<sha256 hex>"}'
# 200 {"registered":true,"first_seen_at_iso":"2026-09-06T11:19:10Z",
#      "first_pdr_id":"1e2f1f30","registrations":7,"anchored":true,
#      "verify_url":"https://verify.aotrust.link/s/1e2f1f30","previous_version":null}
# 200 {"registered":false}   - this exact file was never registered, by anyone

POST /v1/verify/file

Same check for raw bytes: send the file as application/octet-stream (up to 32 MB); the server hashes it as it streams and answers with the same fields. On verify.aotrust.link the file never leaves the device - the browser computes SHA-256 locally.

Both endpoints return registration facts only: no keys, no payer, no file names, no personal data. Rate limit 30 requests/hour and 3/minute per IP. What it proves: the artifact existed at a known time and holds the earliest registration position in the AOTrust registry. What it does not prove: authorship, ownership or legal title.

Verification API

All verification endpoints are public and require no authentication; they return HTTP 200 JSON.

Web verifier (no code)

Paste any PDR bundle (Base64) and verify in the browser: https://verify.aotrust.link/?pdr={pdr_b64}

No receipt? Drop a file or a SHA-256 on the same page, or call POST /v1/verify/hash - see First registration above.

GET /v1/pdr/verify/{pdr_b64}

curl -s https://api.aotrust.link/v1/pdr/verify/<base64url PDR>

GET /v1/pdr/settled?superseded_by_hash={hash}

Lookup the final SETTLED PDR for a PROVISIONAL work_hash (two-phase escrow flows).

Anchor API (cumulative log)

GET /v1/anchor/status                     # latest anchor + size/root/near_tx
GET /v1/anchor/proof/{seq}                # RFC 9162 inclusion path for a ledger seq
GET /v1/anchor/consistency?from=&to=      # RFC 9162 consistency proof between anchors

Offline verification without a server: pdr_parser.py. Documentation source: aotrust-skills.

© 2026 AOTrust · AOTrust Protocol Contributors · Released under the MIT License