"Verifiable credential" is a phrase that has been carrying a lot of weight in agent security discussions lately, usually without anyone opening it up. So let us open it up. A credential an AI agent can carry is not a token issued from a database and looked up on every call. It is a small JSON document that proves itself: a signature over a fixed payload, checkable by anyone holding a public key, with no shared session, no callback and no prior relationship between the agent and the service it is talking to.
That last clause is the whole reason the format exists. An agent showing up at a vendor it has never met cannot present a session — there is no session to present. It has to present evidence.
What is actually in the document
The signed payload is deliberately boring, and every field is load-bearing. In Notlogin's schema the canonical payload commits to:
- Who it is for — a vendor slug plus the vendor's URL as registered at issuance time. Pinning the URL inside the signature matters: without it, a vendor could later change its base origin and every credential ever issued would silently authorize the new one.
- What it permits — a scope (read, write, admin) and a USDC budget, denominated in cents so there is no float ambiguity in the bytes being signed.
- How long — an expiry in unix seconds. Credentials end by default, which removes the single largest category of credential incidents: the one nobody remembered was still valid.
- Who stands behind it — an opaque user id and a short pseudonymous handle, plus the list of proofs that human passed (
email,sms,wallet, KYC). Not a name, not an address. The vendor learns the assurance level, not the person. - A nonce — 32 random bytes that make this credential a distinct object even if every other field is identical to another. This is the handle revocation pulls on.
Before signing, that object is serialized canonically — keys sorted, no whitespace — so that the same logical credential always produces the same bytes. Without a canonical form, two verifiers can disagree about whether a signature is valid simply because their JSON serializers order keys differently. Canonicalization is the unglamorous detail that makes the rest work.
Why Ed25519
Ed25519 is the default for this kind of work for reasons that all point the same direction: 64-byte signatures and 32-byte public keys, verification in well under a millisecond, deterministic signing (no per-signature randomness to get catastrophically wrong), and no curve-parameter or padding choices for an implementer to misconfigure. It ships in Node's standard crypto, in Go, in Python, in every language a vendor is likely to be writing.
Compare it to the alternative a lot of teams reach for: a JWT signed with a shared HMAC secret. That works, right up to the moment you have more than one verifier — because now every party who can check a credential can also mint one. Public-key signatures separate those two capabilities. The broker holds the private key; everyone else gets to verify and nothing more. That asymmetry is what lets a vendor accept credentials from a broker it has no contract with.
Offline verification, and the trade-off nobody names
The verification path is: fetch the issuer's public key once from /.well-known/notlogin-issuer.json, cache it, then check the signature locally. No network call per request, no dependency on the broker being up, no latency added to your hot path. In Notlogin's SDK that is one call — verifyCredential(vcJson, { vendorSlug, requiredProofs }) — and it is the entire integration.
Here is the part that usually gets skipped in enthusiastic write-ups of verifiable credentials: a purely offline check cannot see a revocation. A signature is a statement about the past — the issuer signed these bytes — and nothing about the present. If the human killed that credential five minutes ago, the math still checks out. Offline mode also cannot read the budget ledger, because remaining spend is state, and state does not live in a signature.
Which is why the SDK defaults to online mode: verify the signature locally first (fast local fail on a forged or expired credential, no network wasted), then confirm revocation status and remaining budget with the broker. Offline mode is the right choice for genuinely disconnected verifiers or for a cheap pre-filter, and the wrong choice for anything where a revoked credential is a problem. Choosing between them is a real decision about your risk bar, not a checkbox — and it is the honest answer to "is this offline-verifiable?" Yes, with a named gap.
Revocation by nonce
Because every credential carries a unique nonce, revocation is a single operation that invalidates that credential and only that credential — every copy of it, wherever it was replicated, including into an agent's context, a log line, or a second agent it was handed off to. Nothing else the human issued is affected, no keys rotate, no other vendor sees a disruption.
Set that against revoking a leaked provider API key, which typically means rotating a secret that several legitimate systems are also using, at an hour you did not choose. The nonce turns containment into a small, boring action. That difference — an emergency versus a click — is most of the practical value, and it is why an injected agent leaking a credential is survivable in a way that a leaked key is not.
Layering: wallet co-signature and on-chain anchoring
The broker signature is the primary proof and always present. Two optional layers cover the same canonical payload, so adding them never invalidates what was already there:
- A wallet EIP-712 signature. The user's own key co-signs the payload, so a third party can confirm a specific EVM address authorized this credential — not merely that Notlogin says so. It removes the broker as a single point of trust for that claim.
- An on-chain anchor. The credential hash is emitted as a log on Base, giving an independent, tamper-evident timestamp that anyone can check without asking the issuer anything at all.
Most vendors will never need either. They exist because "trust the broker" is a fine default and a bad ceiling.
What a vendor does with one
Verify the signature, read verifiedProofs, apply your own bar. A newsletter API may be perfectly happy with email proof; a payments endpoint can demand email, SMS, wallet and KYC before it grants anything — and the SDK fails fast, locally, when the credential does not clear it. What you get in return is an accountable actor at the door instead of an anonymous bearer key, with the agent and the human distinguishable in your own logs. It is a five-line integration, not an identity project — the same shape as the formless signup flow it replaces.
Verifiable credentials are not magic and they do not make bearer tokens stop being bearer tokens. What they do is make the thing an agent carries small, scoped, expiring, budgeted and killable — so that losing one is an incident with a size you picked in advance. Verify once and issue one, or read how the broker model works end to end.