Verus Verify a claim Get Verus

Developers

Three endpoints anybody can call, and one you should

Verus publishes a small open surface on purpose. You can ask any deployment what it is and what its database is incapable of holding, and you can check an identity claim against the deployment that issued it, from a browser, on any origin, with no account and no key. That is the whole point: the claims Verus makes about itself are meant to be checked rather than believed.

The base URL for the deployment this site describes is https://api.verusapp.co.uk. A sovereign deployment is a different host answering the same routes, which is why nothing below hardcodes ours.

API reference OpenAPI 3.1 document

The reference is served by the deployment itself and read from it live, field by field. The OpenAPI document covers the open routes and loads into Swagger Editor, Postman or any OpenAPI tool.

Questions, access, or something you want that is not here: developers@verusapp.co.uk. A person reads it.

The open endpoints

All three carry access-control-allow-origin: * and accept GET and OPTIONS, so a page on your domain can call them directly. There is no key to obtain and no registration. Because your browser makes the call, the deployment sees you and this website does not.

GET /v1/health

Whether the deployment is answering, and its clock.

{ "status": "ok", "time": 1787591603 }

GET /v1/deployment

What this deployment is, what it holds, and what it declares it never holds. The last two are computed from the live database schema on every request rather than written down, so the answer cannot drift from the thing it describes. Open it in a browser for a readable reference; send Accept: application/json, or add ?format=json, for the raw response.

{
  "name": "Verus",
  "mode": "standard",
  "jurisdiction": "GB",
  "deploymentKey": "yDEBxYT4lUNq...",
  "confrmoLogin": true,
  "push": true,
  "subscriptions": true,
  "limits":     { "maxEnvelopeBytes": 65536, "maxQueuedEnvelopes": 5000, ... },
  "holds":      { "account": ["address", "identity_key", ...], ... },
  "neverHolds": { "account": ["name", "phone", "email", "ip", ...], ... }
}

GET /v1/claims/:id 60 requests a minute

Everything this deployment will say about one identity claim. The signature is checked against the deployment key on every call, so a forged claim is caught here rather than believed.

{
  "id": "...",
  "address": "7PDM0F7XND2Y259JFN9XJQTM",
  "rpDomain": "verusapp.co.uk",
  "method": "confrmo_session_consume",
  "issuedAt": 1787500000,
  "expiresAt": 1787586400,
  "revoked": false,
  "expired": false,
  "live": true,
  "assurance": "confirmed",
  "checkedAt": 1780000000,
  "signatureValid": true,
  "signature": "...",
  "issuer": "yDEBxYT4lUNq..."
}

Everything else on the deployment requires a signature, and that is not a paywall: those routes act on somebody's account, and an account here is a key rather than a login, so there is nothing to authenticate with except the key.

Reading a claim properly

If you build one thing against Verus, build this. A verifier that answers yes or no is not much of a verifier: a revoked claim still carries a perfectly valid signature, and the difference between somebody withdrawing their identity and somebody never having had one is the difference between a lapsed customer and a person lying to you.

AnswerHow you read itWhat it means
Live live: true Issued by this deployment, signature checks out, not expired and not withdrawn.
Expired expired: true, signatureValid: true Genuine, and past its expiry. Claims are short lived on purpose, so this is ordinary rather than suspicious.
Revoked revoked: true, signatureValid: true Genuine, and withdrawn since. The signature still verifies, which is exactly why revocation has to be reported separately.
Forged signatureValid: false A record carrying a signature this deployment key did not make. Treat as hostile.
Unknown HTTP 404 unknown_claim No such claim here. Not the same as forged: check you are asking the deployment that issued it.

Assurance is a separate question from validity

live: true tells you the claim is real. It does not tell you what it says. That is assurance, and there are two values:

approved means the holder of a Confrmo account approved a login to this relying party. Somebody with access to that account said yes. confirmed means Confrmo additionally asserts that a live face was matched against an identity document it checked, and checkedAt tells you when.

If your reason for asking is is this person who they say they are, approved is not the answer to that question and treating it as one is the mistake this field exists to prevent. Read both, always.

A claim is a statement about an identity check at a moment in time. It is not a recommendation, a credit decision or a character reference, and Verus is not in a position to offer any of those.

Everything else

How a request is signed

There is no bearer token and no session, because there is no account in the ordinary sense: an address is the fingerprint of a key made on a device, so the key is the only thing there is to authenticate with. Every other route on the deployment expects this header.

Authorization: Verus-Sig v=1,a=<address>,k=<device id or identity>,
                         t=<unix seconds>,n=<nonce>,s=<base64url signature>

The signature is Ed25519 over these six lines, joined by newlines with no trailing newline:

verus-request-v1
<METHOD>
<path including query>
<t>
<n>
<base64url sha256 of the raw request body>

Three properties fall out of that, and each one is deliberate. The body digest is inside the signature, so a proxy cannot swap the body. The path is inside it, so a signature captured for one route cannot be replayed at another. And the nonce is recorded until the clock skew window closes, so a captured request cannot be replayed at all.

What this page does not give you

Said plainly, because a developer finding out by wasting an afternoon is worse than being told now, and because the rest of this site holds itself to the same rule.

  • No SDK and no client library. There is a working reference client in the codebase and it is not published.
  • No OpenAPI document for the signed surface. The OpenAPI document covers the open routes above and nothing else; the signed surface is not specified anywhere you can read.
  • No published protocol specification. The messaging layer is X3DH and a Double Ratchet with standard primitives, and naming those is not the same as letting you check the composition. Until it is written down and reviewed, treat the cryptography as unaudited by anybody outside this project.
  • No third party security audit. What is and is not certified is set out on the security page, including that there is no ISO 27001 certificate of our own, no SOC 2 report and no penetration test yet.
  • No versioning promise beyond the three routes above. Those answer /v1/ and will keep answering it.

If you are building something that needs any of the above, say so and it moves up the list. The fastest way to make a specification exist is somebody waiting on it.

developers@verusapp.co.uk How Verus is built