aotrust-protocol SDK
Asyncio-native Python SDK for the AOTrust Notary API — cryptographic proof-of-existence for AI agent outputs.
Install
pip install aotrust-protocol
Quickstart
Free tier — no API key, no wallet (fastest way to try)
import asyncio, hashlib
from agent_notary import NotaryClient
async def main():
# IMPORTANT: no /v1 suffix — the SDK appends API paths itself.
client = NotaryClient(base_url="https://api.aotrust.link")
work_hash = hashlib.sha256(b"my artifact text").hexdigest()
result = await client.shield_free(work_hash)
job_id = result["job_id"] # keep this UUID — it is the handle
print("job_id:", job_id)
# Check status BY job_id (not by the artifact text!)
status = await client.get_status(job_id)
print("status:", status.status) # PENDING → anchored (anchor batches)
# Fetch + verify the PDR
pdr = await client.get_pdr(job_id)
print("verify in browser:", pdr.verify_url)
assert (await client.verify_pdr(pdr.pdr_b64))["valid"]
asyncio.run(main())
Free tier: 5 PDR / 24h per IP. Examples: examples/04_free_tier.py.
Witness mode (pre-paid tx_hash)
import asyncio
from agent_notary import NotaryClient, NotarizeRequest
async def main():
client = NotaryClient(
api_key="your-api-key",
base_url="https://api.aotrust.link" # no /v1 suffix!
)
# Submit notarization
req = NotarizeRequest(
tx_hash="EzrfDW5b...",
work_hash="599d6999...",
agent_sig="base64_sig_A...",
agent_pubkey="aff91a18...",
)
result = await client.notarize(req)
print(f"Job: {result.job_id}")
# Poll for PDR — status/pdr calls always take the job_id returned above
status = await client.wait_for_pdr(result.job_id, timeout=60)
if status.is_anchored:
pdr = await client.get_pdr(result.job_id)
assert pdr.verify(client.notary_pubkey)
print("PDR Valid: YES")
asyncio.run(main())
Why no
/v1?base_urlmust behttps://api.aotrust.link. The SDK already builds/v1/...request paths; adding/v1yourself produces/v1/v1/...→ HTTP 404 on every call. This bit a real user (2026-09-29: quickstart copy-paste + status lookups by artifact text instead of job_id).
Configuration
| Env Var | Constructor Arg | Description |
|---|---|---|
NOTARY_API_KEY |
api_key |
API key for auth |
NOTARY_API_URL |
base_url |
API base URL |
NOTARY_PUBKEY |
notary_pubkey |
Notary Ed25519 public key (hex) |
Endpoints
| Method | Path | Description |
|---|---|---|
| POST | /v1/notarize |
Submit notarization |
| GET | /v1/status/{job_id} |
Poll job status |
| GET | /v1/pdr/{job_id} |
Get PDR |
| POST | /v1/notarize/quote |
Get price quote |
| GET | /.well-known/agent.json |
MCP Server Card |
| GET | /openapi.json |
OpenAPI 3.0 spec |
PDR Verification
pdr = await client.get_pdr(job_id)
is_valid = pdr.verify(notary_pubkey_hex="9c7d64bb...")
Uses NEP-413 raw-buffer verification. No SHA256 pre-hash.
Error Handling
from agent_notary.exceptions import (
NotaryAuthError, # 401 (authenticated CI surfaces; anonymous x402 gives 402 instead)
NotaryPaymentError, # 402 x402-challenge / 403
NotaryNotFoundError, # 404
NotaryValidationError, # 400/422 — invalid params, INVALID_AGENT_SIGNATURE
NotaryConflictError, # 409 — tx_hash/job_id already used (idempotency)
NotaryServerError, # 5xx, carries status_code
NotaryError, # base — safety net
)
try:
result = await client.notarize(req)
except NotaryAuthError:
print("Invalid API key")
except NotaryPaymentError as e:
print(f"Payment/sig failed: {e}")
except NotaryValidationError as e:
print(f"Bad request or invalid signature: {e}")
except NotaryConflictError:
print("This tx_hash/job_id was already used — generate a new one")
except NotaryError as e:
print(f"Other SDK error: {e}")
Development
pip install -e ".[dev]"
pytest tests/ -v
Metadata
Release files for aotrust-protocol 2.3.7
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| aotrust_protocol-2.3.7.tar.gz | 14.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| aotrust_protocol-2.3.7-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 25.1 kB
Release files / aotrust_protocol-2.3.7.tar.gz
| Download URL | aotrust_protocol-2.3.7.tar.gz |
|---|---|
| Size | 14.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9c59e1a0bd5b66f9c0268bb0ba574de3573c2020a0d6e18c5c836db59c44f8c8
|
|
BLAKE2b-256 checksum How to use checksums |
a99ee64763194161b860516696891a905679e81a20fe8c2ae053b197dfdbc4c9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Release files / aotrust_protocol-2.3.7-py3-none-any.whl
| Download URL | aotrust_protocol-2.3.7-py3-none-any.whl |
|---|---|
| Size | 11.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f2aac881f411aee57b593ca76dbd4159ca099c8a0dfca53231cd20452df59840
|
|
BLAKE2b-256 checksum How to use checksums |
8d7e09ab6207556d8c023a9cd5d9d4d2cefb82124d516886d0c5bc2326edafdf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|