LeadProof API reference

Everything you can do in the portal, you can do over HTTP with your account API key. JSON in, JSON out.

Base URL & authentication

All endpoints are under https://libretto.pingproof.ai. Authenticate every request with your account API key as a Bearer token (find it in Setup → API access):

Authorization: Bearer <your_api_key>
Content-Type: application/json

The API key is account-level — it can spend credits and acts with full permissions. Keep it server-side and secret; never embed it in a browser page. (The widget token from Setup is different — that one is public and only used by the capture script.)

Each endpoint below lists its credit cost. For what a credit costs in dollars, volume tiers, and bundles, see LeadProof Pricing →. Requests that would overdraw your balance return 402 with { "error": "insufficient credits" } and charge nothing; all other error responses are also non-charging.

Verify — public, no auth

POST/api/verify· auth: none · rate-limited per IP · cost: free
Request
{ "cert_id": "pp_…", "hash": "optional — integrity/package/disclosure hash to check" }
Success 200
{
  "found": true,
  "integrity_reproduced": true,   // sealed content still hashes to the recorded value
  "genuine": true,                // only present when "hash" was supplied
  "tsa": "digicert",              // or "pending" / null
  "tsa_verified": true            // RFC-3161 token cryptographically verified
}
Failure
404-shaped body: { "found": false, "genuine": false, "integrity_reproduced": false }
422: { "error": "cert_id is required" }
429: { "error": "rate limit exceeded" }

There is also a browser tool at https://libretto.pingproof.ai/verify (requires both the certificate ID and its hash) and a re-hash-from-storage check at GET /api/verify-archive?cert_id=pp_… (public, rate-limited).

Check — does a phone/email match this cert

POST/api/check· auth: Bearer · cost: 0.25 (0 when nothing's on file to compare)
Request
{ "cert_id": "pp_…", "phone": "8135550142", "email": "optional" }
Success 200
{
  "cert_id": "pp_…", "success": true, "checkable": true,
  "match": true, "phone_result": "match", "email_result": null,
  "charged": 0.25, "balance": 812.5, "already_claimed": true
}
No data on file (free)
// The cert has no phone/email hash for the field(s) you sent — nothing to compare, not charged:
{ "cert_id": "pp_…", "success": true, "checkable": false, "charged": 0, … }
Failure
401 authentication required · 402 insufficient credits
404 Certificate not found · 422 cert_id and at least one of phone/email are required

Check · bulk

POST/api/bulk-check· auth: Bearer · cost: 0.25 per item
Request
{ "items": [ { "cert_id": "pp_…", "phone": "8135550142" }, … ] }   // max 500
Success 200
{ "results": [
  { "cert_id": "pp_…", "success": true, "checkable": true, "match": true,
    "phone_result": "match", "email_result": null, "trust_score": 92, "trust_tier": "certified" },
  { "cert_id": "pp_…", "success": false, "error": "Certificate not found" }, … ] }
Failure
422 a non-empty items array is required · 422 Maximum 500 checks per batch

Also reachable at the legacy alias POST /api/bulk-verify. Every item returns existence + hashed phone/email match + trust_score/trust_tier, same as single Check.

Claim — lock a cert to your account

POST/api/claim· auth: Bearer · cost: 1 (5-yr) · 2 (7-yr)
Request
{ "cert_id": "pp_…", "retention_years": 5 }   // 5 or 7; defaults to 5
Success 200
{ "claimed": true, "already_claimed": false, "cost": 1,
  "retention_years": 5, "retention_until": "2031-07-15", "balance": 811.5 }
Idempotent
// Re-claiming returns without charging:
{ "claimed": true, "already_claimed": true, "retention_years": 5 }
Failure
402 insufficient credits · 404 cert not found

Claim · bulk

POST/api/bulk-claim· auth: Bearer · cost: 1–2 per newly-claimed cert
Request
{ "cert_ids": ["pp_…", "pp_…"], "retention_years": 5 }   // max 500; 5 or 7
Success 200
{ "results": [ { "cert_id": "pp_…", "claimed": true, "already_claimed": false }, … ],
  "claimed": 12, "already_claimed": 3, "total": 15 }
Notes
Already-claimed certs are skipped (no charge). A cert you can't afford is reported
{ "error": "insufficient credits" } and the rest continue. Each newly-claimed cert fires
your active Auto-Confirm rules automatically.

Confirm — AI compliance checks

POST/api/confirm· auth: Bearer · requires claim/ownership · cost: 1 checklist + 1 custom
Request
{ "cert_id": "pp_…",
  "check_keys": ["tcpa_express_consent", "clear_and_conspicuous"],  // preset checklist (flat 1 credit)
  "custom_question": "optional free-text question (adds 1 credit)" }
Success 200
{ "cert_id": "pp_…", "results": [ { "check_key": "…", "verdict": "pass|fail|…", "analysis": "…" } ],
  "charged": 1, "cost_by_key": { … }, "balance": 810.5 }
Failure
400 check_key, check_keys, or custom_question is required · 402 insufficient credits · 404 cert not found

Drift — re-verify archived disclosures

POST/api/drift· auth: Bearer · requires claim/ownership · cost: 2
Request
{ "cert_id": "pp_…" }
Success 200
{ "cert_id": "pp_…", "drift_check_id": 42, "changed": 1, "total": 3,
  "items": [ { "source_url": "…", "changed": true, "archived_hash": "…", "live_hash": "…" }, … ] }
Failure
400 no archived disclosures to compare · 402 insufficient credits · 404 cert not found

Defend — sealed evidence package

GET / POST/api/defend· auth: Bearer · requires claim/ownership · cost: 200 (POST)
Preview (free)
GET /api/defend?cert_id=pp_…&format=html   // or format=pdf&inline=1 — regenerated, not the sealed artifact
Generate sealed package
POST /api/defend  { "cert_id": "pp_…", "kind": "evidence" }   // or "attestation"
Retrieve a paid export
GET /api/defend?cert_id=pp_…&export=<export_id>   // streams the sealed PDF from storage
Failure
402 insufficient credits · 404 cert / export not found · 503 evidence storage not configured

Capture — mint a certificate (widget)

POST/api/capture· auth: widget_token (not Bearer) · cost: free
Request
{ "token": "<widget_token>", "page_url": "https://…", "consent_html": "…", "consent_text": "…",
  "disclosure_urls": ["…"], "turnstile_token": "…", "phone_value": "…", "email_value": "…", "signals": { … } }
Success 200
{ "cert_id": "pp_…", "trust_score": 92, "trust_tier": "certified", "tsa": "digicert", "integrity_hash": "…" }
Notes
What the embedded capture script calls — token-based (the domain's widget_token), NOT the Bearer
API key. Production captures must run on a verified domain and pass the bot challenge on that domain.

Domains

GET / POST / DELETE/api/domains· auth: Bearer · create · cost: free
Manage
GET    /api/domains                                  // list -> { domains: [{ domain, status, widget_token }] }
POST   { "domain": "yoursite.com" }                  // add -> returns a DNS verification_token
POST   { "domain": "yoursite.com", "action": "check" } // verify ownership via the DNS TXT record
DELETE /api/domains?domain=yoursite.com

Auto-Claim rules

GET / POST / DELETE/api/auto-claim· auth: Bearer · claim · cost: claim cost per auto-claimed cert
Manage
GET    /api/auto-claim                               // list rules
POST   { "domain": "yoursite.com", "retention_years": 5 }  // certs captured here are claimed at capture time
DELETE /api/auto-claim?domain=yoursite.com
Notes
A matching capture is claimed automatically at capture time (charging the claim cost), which in
turn fires your Auto-Confirm rules on that cert.

Auto-Confirm rules

GET / POST / DELETE/api/auto-checks· auth: Bearer · confirm · cost: confirm cost per claimed cert
Manage
GET    /api/auto-checks                              // list rules
POST   { "name": "TCPA baseline", "check_keys": ["autodialer_disclosure", …],
         "custom_question": "optional", "source_url_filter": "optional — page URL contains…" }
DELETE /api/auto-checks?id=<id>
Notes
A rule fires automatically, once, when a matching cert is CLAIMED (individual, bulk, or auto-claim) —
prospectively, charging the compliance cost per cert; skipped (never blocking the claim) if short on credits.

Auto-Recharge

GET / POST/api/auto-recharge· auth: Bearer · billing · cost: the top-up you configure
Manage
GET  /api/auto-recharge
POST { "enabled": true, "threshold": 100, "amount": 1000 }  // top up when balance < threshold (needs a card on file)

Credit transactions

GET/api/credit-transactions· auth: Bearer · billing · cost: free
List
GET /api/credit-transactions  ->  { "transactions": [ { "type": "…", "amount": …, "created_at": "…" }, … ] }

Portal-only actions (session cookie, not the Bearer API): rotate API key and team management — done from the portal UI (Setup / Team), not the programmatic API.

Setup decision points

Widget token vs. API key — which do I use?

The widget token (public) goes in the capture <script> on your consent page — it mints certificates. The API key (secret) authenticates server-side calls that spend credits (check, claim, confirm, defend). Never swap them.

Demo vs. production capture?

Use data-account for demo certs (flagged, not for real captures) and data-token="<widget_token>" for production. Production capture must run on a verified domain and pass the bot challenge on that domain.

Do I have to claim a certificate before I can Check it?

No. Check works before a claim — that's the point: a prospective buyer can verify a cert exists and that a phone/email matches it (via hashed comparison), and see its trust signals, before purchasing. Only the full cert content is gated behind a claim. checkable:false just means the cert has no phone/email on file for the field(s) you sent (nothing to compare) — it is not about claiming, and it isn't charged.

5-year vs. 7-year retention?

Retention sets how long the sealed evidence is kept. 5 years (1 credit) covers the FTC TSR recordkeeping baseline; 7 years (2 credits) is the longer upgrade for stricter internal or state requirements.

Which verb proves what?

Verify = is the seal genuine/untampered (free, public). Check = does this consumer's phone/email match the cert. Confirm = does the consent language meet a compliance rule (AI). Drift = have the linked disclosures changed since capture. Defend = produce the court-ready sealed evidence package.

Unclaimed certificates

A certificate not claimed within 90 days of capture is archived out of your active list. Claim the ones you intend to use in evidence before the deadline shown on My Certificates.

← back to Setup

LeadProof™ is a proprietary product and service of LeadOpera LLC, a Colorado limited liability company, operated through its independent website. LeadOpera™ and LeadProof™ are trademarks of LeadOpera LLC; wordmark applications pending. Unauthorized use of these marks is strictly prohibited. The consent-certification method used by LeadProof is patent pending. © 2026 LeadOpera LLC. All rights reserved.