Public verification

Every recipient can verify, no account required

A seal that only the issuer can verify is not a seal — it is a private claim. We expose a public verification API that any recipient (a building inspector, a client, a regulator) can hit without logging in. No account, no friction, no dependency on EngineeringID being there in the future. Just bytes, hashes, and PKI.

Executive summary

POST /v1/verify/pdf accepts a hash and a verification code. It returns whether the seal is valid, who issued it, and when. It is rate-limited (60/min/IP), CORS-permissive on this route only, and works without authentication.

For the truly paranoid case (or an EngineeringID outage), verification works fully offline: the X.509 signature, the RFC 3161 timestamp token, and the embedded certificates are all the verifier needs. Acrobat does this natively. So does openssl. So does any standard X.509 toolchain.

Our commitments

Five rules for the verification surface

01

No account required

The verifier is the recipient — a building inspector, a counterparty, a regulator. Forcing them to create an account creates exactly the friction that makes verification not happen.

02

Verification is offline-capable

Our infrastructure can disappear and the seal still verifies. The X.509 + RFC 3161 envelope is self-contained; any X.509-aware tool can verify without contacting us.

03

The verification answer is unambiguous

Three states: valid, tampered, not_found. No 'mostly valid' or 'valid with warnings.' If anything in the integrity chain is off, the answer is tampered.

04

Verification leaks nothing about the document

The verify endpoint returns issuer credentials, seal time, and validity — never the document content, never sensitive metadata. A leaked verification code does not expose what was sealed.

05

Rate limits protect, do not punish

60 requests per minute per IP is more than any legitimate verifier needs and less than any abuser wants. If you have a reason to need more, talk to us.

Implementation — the public API

What the verify endpoint actually does

Endpoint POST /v1/verify/pdf Public, no auth required
Request body { hash, code } SHA-256 hex hash + Base32 verification code
Response valid / tampered / not_found Plus issuer credential and seal timestamp on valid
Rate limit 60 req / min / IP On the dedicated :verify_api bucket; trusted-proxy IP extraction
CORS Permissive Allow any origin, POST/GET/OPTIONS — only on this route
Client identification X-EngineeringID-Client header Optional: chrome_extension, acrobat_plugin, etc.
Logging Every request audited Source IP, code prefix, response status — recorded in the verification_attempts log for the issuing org
Offline path No API call needed X.509 + RFC 3161 verification works without us; standard PKI tools confirm validity

Implementation — the verification surfaces

Where verifiers actually run

Public web page /verify Paste a code or upload a PDF; instant answer for non-technical verifiers
Chrome extension extensions/chrome (built; store listing pending) Manifest V3; scan active tab PDF, paste code, drop-PDF on popup
Adobe Acrobat plugin extensions/acrobat (built; exchange listing pending) UXP Manifest v5, Acrobat DC 22.0+; verify active doc
Direct API Any HTTP client curl, fetch, Python requests — same endpoint, same response shape
Native PDF reader Acrobat / Foxit / Preview X.509 signature visible in the document's signature panel; offline verifiable
openssl / commandline PKI cms_verify The seal is a standard PKCS #7; openssl confirms validity without EngineeringID

The full picture

What is built, what is being built, and what we chose not to build

Live today

POST /v1/verify/pdf public API

Live

No auth, rate-limited, CORS-permissive on this route only.

Public web verification page

Live

Paste a code or upload a PDF; non-technical-recipient-friendly UI.

Offline verification via standard PKI tools

Live

X.509 + PKCS #7 + RFC 3161 — Acrobat, openssl, any X.509-aware tool works without us.

Audit-logged verification requests

Live

Every verify call records source IP, code prefix, result, and response time to a per-org verification log queryable by the issuing org. Verification activity is separate from the hash-chained audit_logs surface used for sealing, MFA, and credential-manifest events; chaining verify requests is on the roadmap.

Building now

Chrome Web Store extension

Building now

Built in repo at extensions/chrome (Manifest V3); store listing pending.

Scan active tab PDFs, paste code, drop-PDF on popup.

Adobe Acrobat plugin

Building now

Built in repo at extensions/acrobat (UXP Manifest v5, Acrobat DC 22.0+); exchange listing pending.

Verify active document, paste code.

iOS / macOS / Android verification apps

Building now

Native mobile and desktop apps for site inspectors and on-the-go verification.

gRPC client contracts are locked at v1; native UI is the build target.

Bulk verification API

Building now

Submit a list of (hash, code) pairs; receive a paginated batch result. Useful for archive audits.

Verification result signing

Building now

The verify endpoint signs its response so the verifier can prove they got a real answer from us, not an MITM-injected reply.

Roadmap

QR-code on the visible seal

Roadmap

Optional embedded QR linking to the verification page. Many engineers prefer the seal's existing visual cleanliness; opt-in by org.

Customer-rooted verification API

Roadmap

Self-host a thin verifier in the customer's environment for fully air-gapped verification when our endpoint cannot be reached.

Federated cross-issuer verification

Roadmap

If two compliant platforms exist, a recipient should be able to verify either. Working with peer issuers on a common verification protocol.

Considered & rejected

Account-required verification

Considered & rejected

Forcing a counterparty to create an account is the easiest way to make verification not happen.

Why we rejected it: the verifier is not our customer. We do not need to "engage" them. We need them to confirm a seal in three seconds and move on. Friction at the verification step undermines the entire reason the seal exists.

Returning the document content from the verify endpoint

Considered & rejected

The verify endpoint should confirm validity, not reveal what was sealed.

Why we rejected it: a leaked verification code does not become a leaked document. Validity confirmation is a different question from "show me the document." We answer the first one publicly; the second one requires authentication and authorization.

"Premium verification" tier with faster response

Considered & rejected

Charging for verification is charging the wrong party.

Why we rejected it: the verifier is the recipient — a regulator, a counterparty, an inspector. Charging them to verify the seal someone else sent is exactly backwards. Verification is free at the API; rate-limiting protects the system, not the wallet.

"Verified by EngineeringID" badge that just says it's good

Considered & rejected

A trust badge that does not confirm cryptographic validity is decoration, not verification.

Why we rejected it: every "verified by us" badge that does not perform the underlying check is just a logo. The verification API checks the actual hash and signature; it returns a fact, not a feeling.

Compliance mappings

Controls this surface satisfies

SOC 2 CC7.1

Detection of Anomalies

Verification request log surfaces unusual access patterns

ISO 27001 A.10.1.1

Cryptographic controls

X.509 + RFC 3161 verification primitives are NIST/IETF-standardized

21 CFR Part 11 11.50(b)

Signature manifestation

Verification surfaces signer credentials and seal time

ESIGN Act §101(c)(1)

Consumer disclosure

Verification is freely accessible to any recipient

UETA §13

Admissibility in evidence

Verifiable record by independent X.509 toolchain

For compliance teams

Questions you do not need to call to ask

Does the recipient need an account to verify?
No. The verify endpoint is public, rate-limited per IP, and requires no authentication. The Chrome extension and Acrobat plugin are also free downloads.
What if EngineeringID is down or no longer exists?
Verification works without us. The X.509 signature, the RFC 3161 timestamp token, and the embedded certificates are everything a standard PKI verifier needs. Acrobat, openssl, your CA — all can confirm validity offline.
What information does the verify endpoint reveal?
On a valid seal: the issuer's name, license number, region, and the seal time. The document content is never returned. On an invalid or tampered document: status only.
What's the rate limit and is it negotiable?
60 requests per minute per IP on the dedicated :verify_api bucket. Higher limits available on request for high-volume verifiers (audit firms, regulatory aggregators).
Are verification requests logged?
Yes — every request is recorded with source IP, code prefix (not the full code), result, and response time, and is queryable by the issuing org. The verification log is a separate surface from the hash-chained audit_logs table that holds sealing, MFA, and credential-manifest events; folding verify requests into the same chain is on the roadmap.
Can a verifier prove they got a real answer from us, not an MITM?
Verification result signing is in active development. Today, TLS 1.3 with HSTS preload prevents the most common MITM cases; the additional layer of signing the verification response is the explicit answer to the paranoid case.
Does the verification API support batch requests?
Bulk verification is in active development; submit a list of (hash, code) pairs and receive a paginated batch result. Useful for archive audits and counterparty re-verification at scale.

Verification that works for the recipient

Try the public verification page or download the Chrome / Acrobat plugin to see it in your existing workflow.