Certified consent (Enterprise)
Certified consent is the Enterprise feature set: visitors submit your form — no PRYVC account, no popup — and every submission is sealed into a tamper-evident certificate with a public verification URL. Requires an active business on the Enterprise plan and a verified domain.
The widget
Section titled “The widget”Add one script tag to any page with a form:
<script src="https://cdn.pryvc.com/v1/pryvc.js" data-client-id="pc_your_client_id" data-mode="consent" data-purpose="Discuss insurance options" data-entities="Your Agency|Your FMO LLC" data-form-selector="#lead-form" data-checkbox-selector="#agree" data-disclosure-selector="#disclosure"></script>| Attribute | Required | Meaning |
|---|---|---|
data-client-id |
yes | Your public client id (pc_…) |
data-mode="consent" |
yes | Activates consent mode (no button is rendered) |
data-purpose |
yes | The stated purpose, recorded in the certificate |
data-entities |
yes | Entities receiving the data, |- or comma-separated — the recipient list bound into the fingerprint |
data-sp1-entity |
no | Put on a checkbox in your form, one per recipient, valued with a name from data-entities. When present, the certificate records who was accepted and who was declined and binds both sets into the fingerprint. The SDK only ever reads these — it never ticks one. |
data-form-selector |
no | CSS selector of the form; defaults to the first <form> |
data-checkbox-selector |
no | Consent checkbox that must be checked before certification |
data-disclosure-selector |
no | Element whose text is the disclosure as displayed |
data-disclosure-text |
no | Literal disclosure text alternative |
data-field-map |
no | JSON map of CSS selector → field key, e.g. {"#em":"email"}; heuristics and data-pryvc-field attributes are the fallback |
Behavior
Section titled “Behavior”- On submit, the widget intercepts, collects the mapped fields, captures the disclosure
text, and calls
POST /v1/consent. - On success it injects
<input type="hidden" name="pryvc_cert_id" value="cc_…">and re-submits the form — your backend receives the certificate id with the lead. - It fails open: if certification errors (network, misconfiguration), the form still submits without a cert. Listen for failures rather than blocking your funnel.
Events
Section titled “Events”Both events bubble from the form element:
form.addEventListener('pryvc:consent', (e) => { // e.detail = { cert_id, fingerprint, verify_url }});form.addEventListener('pryvc:consent-error', (e) => { // e.detail = { code }});Programmatic init is also available: window.Pryvc.initConsent({ clientId, entities, purpose, … }).
POST /v1/consent
Section titled “POST /v1/consent”Called by the widget; you can also call it server-side from a verified origin.
{ "client_id": "pc_your_client_id", "fields": { "first_name": "…", "email": "…" }, "disclosure_text": "…as displayed to the visitor…", "entities": ["Your Agency", "Your FMO LLC"], "purpose": "Discuss insurance options", "page_url": "https://yoursite.com/lead"}Constraints: the browser Origin and the page_url host must sit on one of your
verified domains; the business must be active on the Enterprise plan (402 otherwise).
Field keys use the standard PRYVC field vocabulary. Rate limited per IP.
Response (201):
{ "cert_id": "cc_14dyhv5l6av8cslibs", "fingerprint": "7353f891…", "issued_at": "2026-07-27T21:20:18.586Z", "verify_url": "https://verify.pryvc.com/c/cc_14dyhv5l6av8cslibs"}Verification surfaces
Section titled “Verification surfaces”Two public surfaces, no authentication:
- Human page —
https://verify.pryvc.com/c/{cert_id}— a clean verification page for consumers, partners, carriers, and auditors. Every open is recorded as evidence: view count, timestamp, IP, user agent, and OS. Businesses see the view trail in the portal (Consent certs → detail) and the count per cert in the grid. - JSON —
GET https://api.pryvc.com/v1/certs/{cert_id}/verify— for programmatic validation.
GET /v1/certs/:cert_id/verify — public
Section titled “GET /v1/certs/:cert_id/verify — public”No authentication. Returns everything except subject PII (the subject appears masked, e.g.
j***@e***.com): business name, status, entity list, disclosure text and hash, purpose,
origin domain, fingerprint, and timestamps. Hand this URL to carriers, buyers, auditors, or
the consumer.
Certificate API (API key)
Section titled “Certificate API (API key)”Authenticated with your sk_live_… key (Authorization: Bearer), scoped to your own
certificates.
GET /v1/certs?page=1&per_page=20&status=active&subject_email=jane@example.com&q=insuranceGET /v1/certs/:cert_id- List returns masked subjects with paging metadata (
total,page,per_page);subject_emailmatches exactly via a blind index,qsearches the purpose. - Detail returns the decrypted subject fields plus full evidence (page URL, IP, user agent) — treat responses as PII.
Integration AI
Section titled “Integration AI”POST /v1/business/portal/integrate (portal session) with { url, mode: "share" | "consent", purpose, entities } fetches a page on one of your verified domains, maps the form with
Workers AI, and returns a deterministic, paste-ready snippet plus the field mapping. The
same feature is available in the portal UI under Integration AI.
Policy snapshots (terms as of opt-in)
Section titled “Policy snapshots (terms as of opt-in)”When a certificate is issued, PRYVC also captures the origin domain’s privacy policy and terms text as of that moment, keyed by domain and deduped by content hash — certificates issued while the text is unchanged share one immutable snapshot; any policy edit creates a new one. Snapshot capture runs after the 201 response and never delays your form.
- The public verify endpoint lists each snapshot’s kind, source URL, SHA-256 content hash, and capture date.
- The API-key and portal detail endpoints include the full captured text (
policies[]with atextfield), so you can produce the exact wording that was in force at opt-in.
External checkpointing (Engrave)
Section titled “External checkpointing (Engrave)”Every certificate issuance — and every share grant, revocation, and cease acknowledgement — is also anchored into Engrave, an external append-only ledger with Ed25519-signed tree heads and client-verifiable Merkle proofs. What leaves PRYVC is hashes and generic metadata only: the event type, entity id, fingerprint, origin domain, and timestamp — never names, emails, field values, or any linkable identifier.
- The public verify endpoint and page include the anchor receipt (
anchor: ledger tx reference, entry hash, signed-root snapshot, anchor time). - On top of per-event anchors, PRYVC checkpoints its audit hash-chain head into Engrave every 15 minutes, so every audit row is covered even if an individual anchor write was missed, and verifies ledger consistency proofs on each cycle.
- Practical meaning for auditors: rewriting any historical PRYVC record would require consistently rewriting two independent systems and breaking a Merkle consistency proof — evidence packs are available on request.
Anchoring is strictly fail-open: ledger unavailability never delays or blocks a consent flow.
Fingerprint
Section titled “Fingerprint”Each certificate’s fingerprint is a SHA-256 over the canonical JSON of: cert id, business, disclosure hash, sorted entity list, origin domain, purpose, subject hash, and timestamp — and the issuance is recorded in PRYVC’s hash-chained audit log. The exact composition, canonicalization algorithm, and test vectors are published in the open Share Protocol specification. See the compliance guide for what this proves.
Per-recipient consent
Section titled “Per-recipient consent”By default a certificate records every recipient you named. If you need to record which
recipients the visitor actually agreed to — CMS requires this for Medicare marketing — render a
checkbox per recipient and mark each with data-sp1-entity:
<p id="disclosure">Acme Insurance and Partner FMO LLC may contact me about coverage.</p>
<label><input type="checkbox" data-sp1-entity="Acme Insurance"> Acme Insurance may contact me</label><label><input type="checkbox" data-sp1-entity="Partner FMO LLC"> Partner FMO LLC may contact me</label>The certificate then carries entities_accepted and entities_rejected, both bound into the
fingerprint.
The absent case is meaningful. If your form offers no per-recipient checkboxes, both keys are
omitted entirely and the certificate hashes exactly as it did before this feature existed — so
existing integrations are unaffected. An empty entities_rejected means “asked, declined
nobody”, which is a different fact from “never asked”, and the two deliberately do not hash
alike.
A stray data-sp1-entity naming a recipient you did not declare in data-entities is ignored,
so an unrelated checkbox elsewhere on the page cannot silently change what the certificate
commits to.
Withdrawal
Section titled “Withdrawal”A certificate subject has no account with you or with PRYVC, so withdrawal happens on the certificate’s own public verification page: they enter the address recorded on the certificate, receive a six-digit code there, and confirm.
When that happens the certificate moves to revoked, a 10-business-day cease-contact
deadline starts, and the owner on your account is emailed with the certificate id and the
deadline. Nothing is deleted — the record and every hash remain, with the withdrawal
timestamped.
You also receive it programmatically. certificate.revoked is emitted on the
events feed and delivered to your webhooks:
{ "id": "1dc485ed-...", "type": "certificate.revoked", "created_at": "2026-07-31T22:32:51.614Z", "share_id": null, "cert_id": "cc_q3a6goxdvyddqn2dpb", "data": null}cert_id is populated for certificate events and share_id for share events; neither is set
for both. The event carries no personal data — fetch the certificate with your API key if you
need the subject.