Every event in the PAX operational ledger is hash-chained, batched into a Merkle tree, and anchored to external tamper-evident storage. This page exposes the verifier surface so any auditor, investor, or third-party developer can independently reconstruct the chain and confirm inclusion for any fill — without contacting PAX support and without trusting the PAX API.
Refreshes on page load from GET /v1/audit/status. If you see counts, the chain is running.
Three layers of tamper evidence, each independently verifiable by third parties:
All six endpoints are public, read-only, and rate-limited per source IP. Response envelope is the canonical {ok, data, meta} shape.
| Endpoint | Purpose |
|---|---|
GET /v1/audit/status | Live counts + anchor lag + publisher mode. |
GET /v1/audit/batches/latest | Most recent Merkle batch metadata. |
GET /v1/audit/batches/{num} | Inspect any historical batch by batch_num. |
GET /v1/audit/events/{seq} | Inspect a single hash-chained event (full payload + event_hash + prev_event_hash). |
GET /v1/audit/proof/{seq} | Merkle inclusion proof: sibling hashes proving the event is in its batch's merkle_root. |
GET /v1/audit/anchor/{num} | Resolve batch number to external R2 anchor URL (signed payload). |
Enter an event seq below. The page will fetch the event + its Merkle inclusion proof + the batch's merkle_root, then verify the proof entirely in your browser (WebCrypto SHA-256, OpenZeppelin sorted-pair). The result is computed client-side — no need to trust the PAX response.
The verify algorithm is 5 lines. Everything below runs locally against the public endpoints — you never need to trust PAX to compute the answer.
// npm i @predictasiax/api
import { PaxClient, AuditResource } from '@predictasiax/api';
const pax = new PaxClient({ apiKey: 'anonymous' }); // audit endpoints are no-auth
const seq = 110841;
const proof = await pax.audit.getProof(seq);
// Node crypto (sync)
const ok = AuditResource.verifyProof(
proof.event_hash,
proof.batch.merkle_root,
proof.merkle_proof,
);
// Browser / edge (WebCrypto async)
const okAsync = await AuditResource.verifyProofAsync(
proof.event_hash,
proof.batch.merkle_root,
proof.merkle_proof,
);
console.log('Verified locally:', ok); // true
# pip install pax-api
from pax_api import PaxClient
pax = PaxClient(api_key="anonymous") # audit endpoints are no-auth
seq = 110841
proof = pax.audit_proof(seq)["data"]
ok = PaxClient.verify_merkle_proof(
leaf=proof["event_hash"],
root=proof["batch"]["merkle_root"],
proof=proof["merkle_proof"],
)
print("Verified locally:", ok) # True
# 1. Fetch the event + its Merkle proof
curl -s https://api.predictasiax.com/v1/audit/proof/110841 | jq
# 2. Verify in shell (OpenZeppelin sorted-pair sha256)
verify() {
local h=$1 root=$2 shift 2
local proof=("$@")
for s in "${proof[@]}"; do
if [[ "$h" < "$s" ]]; then pair="${h}${s}"; else pair="${s}${h}"; fi
h=$(printf '%s' "$pair" | shasum -a 256 | cut -c1-64)
done
[[ "$h" == "$root" ]] && echo OK || echo MISMATCH
}
// The Merkle algorithm is bit-identical to OpenZeppelin's MerkleProof —
// the proofs returned by /v1/audit/proof/{seq} work on-chain without change.
import { MerkleProof } from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
function verifyPaxEvent(
bytes32 leaf, // event_hash from /v1/audit/proof/{seq}
bytes32 root, // merkle_root from same response
bytes32[] calldata proof // merkle_proof array
) public pure returns (bool) {
return MerkleProof.verify(proof, root, leaf);
}
event_log. If your app routed the trade, the event's payload carries your execution_builder_id — publicly verifiable via /v1/audit/events/{seq}./v1/fees/estimate endpoint and the fill-time settlement path share the same computation. Estimate returned to you before the trade is the same math applied to your settlement — impossible to diverge because both derive from the same code path.api.predictasiax.com were compromised, historical anchors let auditors detect after-the-fact rewrites of past events.seq, the computed hash, and the expected hash. Every legitimate discrepancy report is investigated within 24h.