DEVELOPERS

One paste.
One answer.

A widget whose source you can read today, a sandbox that is not open yet, and a public register wired so this page cannot oversell either. This is also the one page allowed to speak protocol names. Everywhere else they stay folded.

The whole integration.

PLANNED

An age check is two lines in your page. This is not a teaser — it is the API.

<script src="https://orbis.id/v1/widget/orbis-verify.js" defer></script>
<orbis-verify ask="age_over_18" tenant="your-shop"></orbis-verify>

The widget is written and its source is honest work you can audit: no shadow DOM, no external requests, every state narrated for screen readers, and a bundled mock verifier so the whole flow runs on your machine today. What is not live is the hosted script this snippet names, which is why the tag on this section says PLANNED, not almost.

What your page receives

document.addEventListener("orbis:verified", (e) => {
  // e.detail = { session_id, claims_satisfied }
  // That is the entire answer. No name, no birth date, no document.
  fetch("/session/age-ok", { method: "POST",
    body: JSON.stringify({ ref: e.detail.session_id }) });
});

For anything that matters, trust the signed server callback: verify { session_id, claims_satisfied, timestamp, sig } against the platform's published keys; replays are refused by session_id. The browser event is UI convenience.

Honest states are part of the contract: a poll that has not returned renders as "waiting", four consecutive failures render as "lost contact". A non-answer is never rendered as an answer.

The ten-minute path.

PLANNED

No sandbox is running today. Until it opens, this is a preview of the intended path, not instructions.

  1. Get a sandbox key. No sales call, no form longer than one field.
  2. Paste the widget, or curl the session endpoint directly.
  3. Approve the request on the hosted test phone in your browser.
  4. Verify the signed callback against our published keys. Done.

The register row (a hello-world you can run in ten minutes) is the source of truth for this section, and it says PLANNED.

SIMULATED RUN
WHAT A RUN WILL LOOK LIKE
curl -s -X POST https://sandbox.orbis.id/v1/issue/demo 201 { "offer": "openid-credential-offer://…" } open test-phone # accepts the offer ✓ document issued to the test phone curl -s https://sandbox.orbis.id/v1/verify/session/s_42 ✓ { "status": "satisfied", "claims_satisfied": ["age_over_18"] }
TEST PHONE
GIVEN BY · sandbox
Demo proof of age
Claimage_over_18
Statusvalid (simulated)

A drawing of the intended path, marked as one. None of the hosts in the transcript answer today.

The protocols, named precisely.

LIVE

No invented formats. The exact stack the EU's implementing acts cite.

Each protocol job, the standard chosen for it, and the build status of our implementation
The jobThe standardOur implementation
The document format SD-JWT VC — RFC 9901 IN BUILD · P1
Handing a document to a phone OpenID4VCI (Final) IN BUILD · P1
Asking, and answering with only the fields chosen OpenID4VP (Final) + DCQL IN BUILD · P1
Naming an issuer by its own domain did:web IN BUILD · P1

The LIVE tag covers one fact: that these are the formats EU implementing acts cite, a fact about law and specs, not about us. The build tags in the table are the claims about us, and none of them says LIVE: nothing issues yet. The register keeps the two apart.

Two API planes. One law.

PLANNED

The side that checks never pays and never authenticates. The side that issues is keyed and versioned.

The verification plane (did.json, keys, status lists) is meant to be free, unauthenticated, unmetered, and standards-versioned, forever. Signed static files: verification keeps working with every origin of ours down.

The participation plane (issuing, depositing, managing) is keyed, rate-limited, and versioned under /v1 with a published deprecation window. New capabilities arrive as new versioned endpoints. Nothing is silently changed.

"Free forever" is an intention the owner has not signed. Its register row says exactly that.

WHO NEEDS A KEY
Checking a proofno key, no account, no meter
Reading keys & status listspublic, signed, static
Issuing under your brandkeyed · rate-limited · /v1

If checking ever needs our permission, the design has failed.

Your integration never migrates.

PLANNED

The old API's own tests are the acceptance suite for every new engine.

We call it the conformance oracle: a rebuilt engine ships only when the previous platform's contract tests pass against it on the wire. Your integration cuts over unchanged, or the engine does not ship. That is the gate, not a review step.

The same discipline runs outward: sixteen versioned test vectors (versioned, never mutated) and a CLI that checks any implementation against them. Vectors are the contract.

Design commitments, tagged PLANNED until the register can show the gate running.

Every way it can fail, catalogued.

PLANNED

Revoked, expired, bad nonce, wrong audience, clock skew, malformed disclosure — each with a runnable reproduction.

Failure documentation is where integrations go to die, and where this industry is weakest. The plan: every failure mode a verification can produce, documented with a curl line that reproduces it against the sandbox, so your 3am incident matches a page instead of a support queue.

Planned alongside the sandbox it needs. The tag will move when the catalogue exists, not when it is promised.

While the sandbox is closed.