The OID4VP verifier, real endpoints, real policy knobs, and one of them means less than it reads

The verifier side is live and auth-gated on the capture API.

Issuance and presentation are different protocols

OID4VCI gets a credential into a holder's wallet. OID4VP gets a proof out of it, to a verifier. They are separate specifications and a vendor can implement one without the other.

We implement both, in different services: the issuance metadata is published at the capture API's well-known endpoint, and the presentation endpoints live on the capture API too. The Verify application backend has none. If you are looking for OID4VP in the wrong service you will correctly conclude it is not there.

What actually exists

Three endpoints, verified live on 2026-07-31:

endpoint purpose probe result
PUT /v1/presentations/policy set what this verifier will accept 401
POST /v1/presentations/requests mint a presentation request (QR / deep link) 401
POST /v1/presentations/verify verify a returned vp_token 401

A 401 means the route exists and requires credentials. A route that does not exist returns 404, we ran that control, and we ran a known-good endpoint as a positive control too. So a stranger can confirm these endpoints are real without having an account; they cannot confirm what they do. That is a weaker proof than the ones on verification reuse and selective disclosure, and we are grading it as weaker.

The verifier policy, which is the interesting part

A verifier does not just check a signature: it declares what it is willing to accept. The policy supports:

  • requested_claims, which attributes the presentation must carry.
  • accept_min_loa, a minimum assurance level, from our own L1 / L2 / L3 / L3+ scheme.
  • accept_issuers, either every issuer enrolled in the trust registry, or an explicit list of issuer DIDs.
  • freshness_max_days, reject a credential whose underlying verification is older than a chosen window.
  • ttl_seconds, how long a minted request stays valid.

freshness_max_days is the one worth dwelling on, because it is the knob that makes reuse defensible rather than indefinite: a relying party can decide that a verification from fourteen months ago is not good enough for its risk appetite, without having to reject reuse entirely. That is the mechanism by which "verify once" stops meaning "verify once, forever."

Two knobs that mean less than they read

accept_issuers: registry_all currently means "accept Solidus." It sounds like a policy about a diverse ecosystem. The trust registry has one operator, us, and there is no federation. Until there is a second issuer, choosing "any registry issuer" and choosing "Solidus" are the same decision. See vendor lock-in.

Our L1/L2/L3 assurance levels are our own scheme. They are not eIDAS levels of assurance, not an accredited assurance framework, and no external body has evaluated what our levels correspond to. They are useful as a policy dial between our own tiers; they do not import anybody else's meaning.

What this does not do

  • It does not decide whether relying on the credential is reasonable. The policy engine enforces the rules you set. Whether those rules are adequate for your regulator is your call, and reliance records that no unaffiliated party has yet made that call in production.
  • It does not discharge your obligation. Whether third-party verification satisfies a given regulatory duty is unsettled.
  • It does not make an unaudited proof audited. A BBS+ presentation verified by this endpoint is still produced by code nobody independent has reviewed.

Keep reading

Powered by the Protocol

Solidus Verify is one product on the Solidus Network.

Explore the consensus, the validator economics, and the other products on the same identity layer.

The OID4VP verifier, real endpoints, real policy knobs, and one of them means less than it reads · Solidus — Solidus Verify