No custody. No trust required.
PayGate402 doesn't hold your money. The escrow runs in attested code, every settlement event is signed by a publicly-verifiable key, and receipts are single-use replay-protected. Math, not trust.
Verify the audit chain yourself
Every audit event includes a base64url-encoded Ed25519 signature over the canonical event JSON. Pull the chain from /api/v1/transactions/<tx_id>/audit-chain and verify each signature against this key. Tampering with any event breaks the chain — visibly.
{ "algorithm": "ed25519", "public_key_hex": "loading…" } Open raw responseWhat the escrow proves about itself
{
"mode": "simulated",
"backend": "tee_simulator",
"digest": "sha256:8e2c1d…",
"issued_at": "2026-05-15T01:42:11Z",
"key_id": "sim_8e2c1dba9f3c4517",
"warning": "This is a SIMULATED TEE attestation.
Production = AWS Nitro Enclaves."
}Production swaps the simulator for a real Nitro enclave that produces a signed PCR + measurement document. Same interface, no coordinator code changes — the audit chain references the attestation by digest so old sealed events stay verifiable.
Funds are held by attested code (AWS Nitro Enclaves in production, simulator in dev). Neither agent nor provider can rug — the math is the third party.
Every receipt → hold → release → settlement event is signed by the coordinator key. Anyone with a tx_id can independently verify the chain.
We don't custody agent funds and we don't custody provider payouts. Coordinator is a verifier + escrow operator, not a wallet.
60-second TTL, single-use consume on verify. Every receipt has a fresh nonce. Replayed receipts return HTTP 410 + audit-logged.
SOC 2 Type II + PCI-DSS evidence packs ship on Scale tier. Custom data residency + dedicated TEE enclaves available.
Outbound provider webhooks are HMAC-SHA256 signed. Replay-protected with timestamp window. Forensic-grade per-event audit trail.
What's deterministic. What's an LLM.
Anywhere money moves is math and cryptography — not a model guessing. LLMs sit at the edges (advisory, UX). The rail is auditable and replayable line-by-line.
The rail itself
- Ed25519-signed receipts — public key on /security; verify in your browser
- Hash-chained audit log — every event has prior_event_id + signature
- Hard caps — $0.05/tx, $1/run; refused at the gate before any rail call
- Spend grants — per-merchant / per-route caps, pure if/then
- Counter-offer band — accept ≥ floor, reject < floor; no LLM "judges" the price
- Idempotency-Key — same key + body → cached response; replay-safe
- Receipt single-use — 60s TTL in Redis, consumed atomically
- Kill switch — operator-token gated, instant freeze, DB-persistent
- Rail verify — Stripe + Coinbase signatures; cryptographic check
UX + advisory, never policy
- Anomaly detector — 2-stage: fast SQL pre-filter (deterministic) for obvious wallet-drain patterns, then Gemini 2.5-flash as judge only for ambiguous cases. Flags only — never auto-acts.
- Pricing suggestions — Gemini reads counter-offer accept rate + refund rate; writes "try $0.0024 floor" in the dashboard. Operator decides. Doesn't change behavior on its own.
- Voice agent (GPT-4.1 via Retell) — drives natural conversation, calls deterministic tools (add_to_cart, negotiate, checkout). Can't bypass policy: every tool hits the same caps + signatures.
Everything an LLM does is either advisory (suggestion that needs operator action) or a thin wrapper around a deterministic endpoint. The receipt minted from a voice-driven purchase is bit-for-bit identical to one from a curl request.
Self-improvement loop (live today)
- Every payment decision lands in
audit_logwith reasons - Agent reputation increments per successful settlement
- Anomaly detector runs every 15 min, scans patterns, writes findings to
anomaliestable - Pricing engine reads recent accept/reject patterns, surfaces suggested floors
- Operator (today) decides whether to act on findings — closed-loop auto-policy is on the Q3 roadmap
Evals running today
- ✅
make e2e— full handshake (issue → verify → release → audit) + replay-protection invariant + expired-receipt 410 + handler-5xx refund path - ✅ Multi-provider parallel — 1 agent → 3 providers → 23 calls settle in <500ms wall-clock
- ✅
pytest tests/— health, cache prefix, Stripe rail, webhook HMAC - 🟡 AgentPayBench v0 — synthetic adversarial scenarios (planned; eval suite scaffolded)
- 🟡 LLM-as-judge precision/recall — once anomaly detector has a labeled set
Verify a PayGate receipt yourself.
Don't trust this UI. Don't trust the coordinator. Paste any PayGate receipt URL or ID below — the browser re-derives the Ed25519 signature against the published public key, in your own session. The code snippets underneath do the exact same check from your terminal.
fetch(receipt) → JSON.stringify(sorted) → nacl.sign.detached.verify(). import base64, json, httpx
from nacl.signing import VerifyKey
r = httpx.get("https://api.paygate.agentglass.dev/api/v1/receipts/<paste_receipt_id>").json()
sig = base64.urlsafe_b64decode(r["signature"] + "=" * (-len(r["signature"]) % 4))
msg = json.dumps(r["canonical_payload"], sort_keys=True, separators=(",", ":")).encode()
vk = VerifyKey(bytes.fromhex(r["public_key_hex"]))
vk.verify(msg, sig) # raises if invalid; prints nothing on success
print(f"✓ receipt {r['id']} verified — ${r['amount_micro_usd']/1e6:.4f} {r['rail']}")import nacl from "tweetnacl";
const r = await (await fetch("https://api.paygate.agentglass.dev/api/v1/receipts/<paste_receipt_id>")).json();
const b64ToU8 = s => Uint8Array.from(atob(s.replace(/-/g,"+").replace(/_/g,"/") + "===".slice((s.length+3)%4)), c => c.charCodeAt(0));
const hexToU8 = h => new Uint8Array(h.match(/../g).map(x => parseInt(x,16)));
const sortKeys = (o) => Object.keys(o).sort().reduce((a,k) => (a[k]=o[k],a), {});
const canon = new TextEncoder().encode(JSON.stringify(sortKeys(r.canonical_payload)));
const ok = nacl.sign.detached.verify(canon, b64ToU8(r.signature), hexToU8(r.public_key_hex));
console.log(ok ? "✓ verified" : "✗ INVALID");The coordinator's current public key: GET api.paygate.agentglass.dev/api/v1/coordinator/pubkey. Rotate the key, every prior receipt still verifies because the public key is stamped on each signed receipt at mint time.
Threat model
Need a deeper security review?
I share full architecture diagrams, sample audit chains, key rotation policies, and incident response playbooks under NDA — usually a 30-minute call gets you what your security team needs to sign off.