A Petra credential is a compact JWS signed with ES256. You can verify it yourself, in any browser or server, without trusting or even reaching Petra's app servers. The trust is the issuer's published key plus the signature.
One function. It fetches the public issuer registry, checks the signature, and hands you the decoded credential. Works in the browser and in Node 18+ (pure Web Crypto, no native deps).
npm install @petra/verifier-js
import { verify } from '@petra/verifier-js' // jws is the compact credential string (from a QR scan, an upload, an API). const result = await verify(jws) if (result.signatureValid) { // Authentic — signed by a known Petra issuer. console.log('Signed by', result.issuer.name) console.log('Subject', result.credential.credentialSubject) } else { // Signature did not verify — do not trust it. }
If you'd rather not take a dependency, the whole check is four steps with any JWS / crypto library:
curl https://api.petraverify.id/.well-known/petra-issuers.json
| GET /.well-known/petra-issuers.json | The issuer registry — every published issuer key. The root of trust. |
| GET /credentials/{id} | A stored credential by id, including its jws, status, and on-chain anchor (when present). |
| petraverify.id/verify/{id} | The human-readable verify page — what a Petra QR code points to. |
Base URL: https://api.petraverify.id
Petra-the-API only serves data; it never asserts validity. A credential carries its own proof — the issuer's signature over the payload — so verification works even if Petra is unreachable, and a forged or tampered credential fails the signature check. Revocation and key rotation are reflected in the registry; the on-chain anchor lets you confirm a credential existed at a point in time independently of Petra entirely.