Proof Systems & Verification

AdPriva produces three kinds of signed records. Each one is sealed when it is created and anchored on Horizen later. This page explains how each is sealed and who can check it.

Record types

RecordCreated whenSealed withAnchored asWho can check it
View proofThe tag reports a page loadAn HMAC-SHA256 with AdPriva’s private key. The signature is the proof idA Poseidon Merkle root, anchored on HorizenOnly AdPriva can check the HMAC. Anyone can check batch membership against the anchored root
Consent certificateA visitor submits a form marked data-adpriva-consentAn HMAC over the site, form URL, consent-wording hash, checkbox state, timestamp and nonceA SHA-256 Merkle root, anchored on HorizenOnly AdPriva can check the HMAC. Anyone can check batch membership against the anchored root
Consent Evidence certificate (cert_v: 1)A visitor submits a form that declares a registered Legal Bundle (data-adpriva-bundle)An Ed25519 signature over the certificate’s canonical JSON (RFC 8785)Anchored with the consent certificatesAnyone, offline, with AdPriva’s published public key

For consent records, see Consent Certificates — Quickstart and Verifying a Consent Evidence Certificate.

Checking a view proof

  1. Look up the proof id in the Explorer, or call GET https://api.adpriva.com/public/proofs/{proof_id}. No account is needed.
  2. Read its status, validity score and verdict. Once the proof is batched, the response also carries a Merkle inclusion receipt: leaf, leaf_index, merkle_path, merkle_path_indices and hash_version.
  3. Recompute the batch root from the leaf and the path. The API Reference has the algorithm for each hash_version.
  4. Compare your root with the Anchored(merkleRoot) event in the horizen_tx transaction.
  5. For a batch anchored before 2026-09-28, you can also open zkverify_url to see zkVerify’s check of the batch’s zero-knowledge proof. New batches have none (zkverify_status is NOT_APPLICABLE). See Legacy: zero-knowledge step.

Steps 3 and 4 do not rely on AdPriva’s status field. They work offline once you have the receipt and the transaction.

Shortened example response (merkle_path is cut down here; the real path has 20 entries):

{
  "proof_id": "dcea8f8ef8f162c6b7269dd4d1ad24708f6358cbd6fa6d48dd528ab0e5e29b08",
  "type": "view",
  "status": "verified",
  "merkle_root": "0x05f559a4dbb3c8f4cce6434b3e933468cc23a1c5bba2c479275d3349254d5e5c",
  "leaf": "6485",
  "leaf_index": 2,
  "merkle_path": ["18928760214379673151198604163469262720598047531616892520656806346189907746915", "20057140030177622096707912563671758214552331126762024679885238248733466757272", "0", "…", "0"],
  "merkle_path_indices": [0, 1, 0, "…", 0],
  "hash_version": "poseidon",
  "zkverify_status": "NOT_APPLICABLE",
  "horizen_status": "CONFIRMED",
  "horizen_tx": "0x846be1b73a220942c73e04d4772df04a4ca8b19b008cd9ce00aed0d2911ea885",
  "validity_score": 100,
  "verdict": "human"
}

What sealing and anchoring guarantee

GuaranteeHowLimit
A captured event cannot be counted twiceThe server refuses a nonce it has already seen, and the database refuses a second proof with the same signatureIt does not stop someone from sending a new event with a fresh nonce. Scoring is what judges those
A view proof’s sealed fields cannot be changed unnoticedThe HMAC covers the event type, the site, the nonce and the browser’s timestamp. Changing any of them gives a different signature, and the signature is the proof idOnly AdPriva holds the HMAC key. The seal does not cover the score, the verdict or the other stored fields
A batch’s members are fixed in timeThe batch’s Merkle root is in a Horizen transactionFor view batches (hash_version: "poseidon"), each leaf is the proof’s internal number, which the public API returns with the receipt. The root does not cover a proof’s score or verdict. A proof is pending until its batch is anchored
A consent record’s content is fixed in timeConsent batches use the certificate signatures as leaves, and each signature is computed over the certificate’s contentThe seal does not cover the personal fields, which are erased at expiry. See Data-Processor Posture §4
A consent certificate can be checked without AdPrivaEd25519 signature and published key (cert_v: 1 and the record-only cert_v: 2)Older consent certificates use the HMAC seal

Anchoring shows that a record was in its batch when the batch was anchored. It does not show that a person was behind the event, and it does not fix a view proof’s score or verdict. See Proofs of Engagement for how verdicts are given.

{% @mermaid/diagram content="flowchart LR
A\[Tag: view event or consent form]
B\[Ingest server: nonce check and seal]
C\[Database]
D\[Anchor worker: Merkle batch]
E\[Horizen: Anchored event]
F\[Public API and Explorer]

A --> B
B --> C
C --> D
D --> E
C --> F" %}