IXO Credentials is the system IXO uses to issue verifiable credentials to people, keep them in the person's encrypted Vault, share only the claims a service needs, and revoke them. Read this page to understand the parts and how they connect before you integrate as an issuer, a verifier or a wallet. To try the whole chain first, follow Try it on devnet. For the general model of Decentralized Identifiers (DIDs) and credentials on IXO, see Identity and credentials.
Where it runs
IXO Credentials is live on all three networks. Each network has its own Credentials worker and its own Auth Hub wallet; nothing is shared between networks.
| Network | Credentials worker | Worker DID | Auth Hub wallet |
|---|---|---|---|
| Devnet | https://dev.credentials.ixo.earth | did:web:dev.credentials.ixo.earth | https://dev.auth.ixo.earth/credentials |
| Testnet | https://test.credentials.ixo.earth | did:web:test.credentials.ixo.earth | https://test.auth.ixo.earth/credentials |
| Mainnet | https://credentials.ixo.earth | did:web:credentials.ixo.earth | https://auth.ixo.earth/credentials |
Every worker host describes itself at /docs (interactive API reference), /openapi.json (the full contract) and /llms.txt (a short summary for agents), for example dev.credentials.ixo.earth/docs. The library for issuers, verifiers and wallets is @ixo/credentials-kit on npm.
Devnet also has a test issuer and a test verifier for trying the flow. They issue and accept fake credentials only; never use them for real people. See Try it on devnet.
Self is not live yet. Self, IXO's identity verification service, is the reference issuer of the IdentityLevel1 credential. It is built but not deployed on any network, so no IdentityLevel1 credentials exist yet. The pages mark everything that depends on Self.
What it is
IXO Credentials uses open standards end to end:
| Piece | Standard |
|---|---|
| Credential format | SD-JWT-based Verifiable Digital Credentials (SD-JWT VC), format dc+sd-jwt, on Selective Disclosure for JWTs (SD-JWT, RFC 9901), signed with Ed25519 |
| Issuance | OpenID for Verifiable Credential Issuance (OpenID4VCI) 1.0, pre-authorized code flow, offers by reference |
| Presentation | OpenID for Verifiable Presentations (OpenID4VP) 1.0, a subset of the Digital Credentials Query Language (DCQL), encrypted direct_post.jwt responses |
| Revocation | IETF Token Status List |
| Identifiers | did:ixo for people and entities, did:web for services |
IXO implements a profile of each standard, not all of it. For example: no authorization code flow, no transaction codes, no batch issuance, and requests outside the DCQL subset are refused. The exact versions, what is implemented, and how this compares with the European Digital Identity (EUDI) Wallet are on Standards and conformance.
On top of the standards, IXO adds one shared service and one set of rules:
- The Credentials worker lets issuers and verifiers reach a person by their DID. It has four jobs: an offer inbox (credential offers addressed to a DID), a presentation broker (signed proof requests addressed to a DID), a status-list registry (issuer-signed revocation lists) and a public catalog (what each issuer says it issues and what each verifier says it accepts, with the name, logo and card look wallets show). It also keeps each person's block list: the senders that person no longer accepts offers or requests from. It never holds a claim or a credential, and never signs one.
- The IXO Credential Profile v1 narrows each standard to one way of doing things, so every IXO issuer, verifier and wallet checks the same things.
Credential types (vct values) are not hosted on the Credentials worker. New types follow the existing IXO pattern: a type document in the GitHub repository ixofoundation/ns and a protocol entity, as the KYCAMLLevel1 type does. Self's IdentityLevel1 keeps its current vct (https://credentials.ixo.world/types/IdentityLevel1).
The roles
| Role | Does | On IXO |
|---|---|---|
| Issuer | Checks facts, signs credentials, keeps status lists | Any service with a did:ixo entity DID or a did:web DID and an Ed25519 key under assertionMethod. Self (not live yet) and the devnet test issuer are two. |
| Wallet (holder) | Collects, stores and presents credentials with the person's consent | The Auth Hub's /credentials pages, acting with the person's own key, or a wallet a person or team runs themselves with the kit and the person's own keys |
| Verifier | Asks for specific claims from specific issuers and checks the answer | Any service with a did:ixo or did:web DID |
| Registry | Publishes the keys everyone checks against | DID documents on the IXO chain, read through IXO Blocksync, and did:web documents on each service's own host |
Credentials are stored only in the person's Vault, an end-to-end encrypted room on IXO Matrix. The Auth Hub keeps its working data for the wallet (cached offers and requests, the cached Vault index, standing consents, the activity log, its copy of the block list) in a credentials database of its own, separate from the Hub's account database.
How it fits together
The credential travels from the issuer to the wallet, and the presentation from the wallet to the verifier, encrypted to the verifier's key. Neither passes through the Credentials worker. Only the Auth Hub receives webhooks; any other wallet polls the worker as the person.
When to use it
Use IXO Credentials when:
- your service checks something about a person once (identity, age, a qualification) and other services need to rely on that check;
- your service needs proof of a fact about a person without collecting the underlying data, for example "over 18" without a birth date;
- you need to revoke what you issued.
Do not use it for:
- claims about entities, projects or impact outcomes: use IXO claims;
- service-to-service authorization: use UCAN delegations and the patterns in Authentication.
Core capabilities
Issue to a DID
An issuer deposits a credential offer for a person's DID, by reference: a credential_offer_uri at the issuer that mints a fresh, short-lived, single-use pre-authorized code each time the wallet fetches it. The wallet collects the credential over OpenID4VCI. The issuer binds the credential only to a key on the person's DID document, so a leaked code yields nothing without that key. Issue a credential.
Ask a DID for proof
A verifier deposits a signed OpenID4VP request for a person's DID, sends the person a link, and receives an encrypted response at its own endpoint. Request proof.
Revoke and discover
Issuers publish signed status lists to the registry; verifiers read one bit per credential. The catalog tells anyone what an issuer says it issues and what a verifier says it accepts. Status lists and the catalog.
What IXO adds and what stays standard
| IXO addition | Why | Effect on the standards |
|---|---|---|
| Offers and requests addressed to a DID | The standards assume a QR code or link in front of a person | None: the offers and requests are standard objects |
Issuer key from a did:ixo or did:web | SD-JWT VC lets an ecosystem define its key discovery | One mechanism only |
| Subject binding at issuance | Pre-authorized codes are bearer secrets | Issuer-side check, invisible to wallets |
A DCQL subset and an issuer filter on iss | Every wallet must handle every request the same way | Requests beyond the subset are refused |
| Mandatory key binding and status checks | Replay and revocation protection | Stricter than the standards require |
| Catalog | Find what an issuer says it issues or a verifier says it accepts, starting from a DID; the only source of names, logos and card looks | Ignoring it changes nothing |
| Block list at the worker | A person can stop any sender from reaching them | None: only the inbox and the broker apply it |
| UCAN authentication at the worker | Every call is signed by the caller's DID, bound to one request and used once | None: only the worker uses it |
What protects a person
There is no central trust list. The same rules apply to every sender, IXO's own services included. Every DID is its own sender, exactly as written: did:web:example.com, did:web:a.example.com and did:web:example.com:user:alice are three senders, each with its own limits, its own block and its own catalog entry. There is no grouping by domain.
Names, logos and card looks are self-declared. Each comes only from the sender's own catalog entry, never from an offer or a request. Nobody checks them, and a sender can copy another sender's name and look. So none of the protections below depends on a name or a look.
The Auth Hub never shows a web address that a sender supplied, not as a link and not as text to copy. A harmful link would be blamed on IXO. A sender appears only by its name, logo and card look, and the Hub loads logos only through its own media proxy (png, jpeg or webp).
What protects a person:
- The person's block list. A person can block any issuer or verifier. The Credentials worker then refuses that sender's offers and requests for them, and closes the ones already waiting. See Block a sender.
- Two waiting items per sender. A sender can have at most 2 offers and, separately, 2 requests waiting for one person at a time. A sender cannot fill a person's inbox.
- The cryptographic check of every credential. A wallet stores a credential only if the issuer's signature is valid, it is about the person (
sub) and it is bound to the person's key (cnf). A verifier checks the same on every presentation, plus status and key binding. - Each verifier's own choice of accepted issuers. A verifier names the issuer DIDs it accepts for each type. A credential from any other issuer fails the check, whatever name or look it carries.
What a verifier always sees
Selective disclosure hides only the claims the issuer made disclosable and the request did not ask for. Every presentation also shows the verifier, in the clear:
- the person's IXO account ID (
sub, theirdid:ixo, the same at every service); - the holder key (
cnf.jwk, also the same at every service); - the status reference (the status list URL and the person's index in it);
- the issuer (
iss), the type (vct) and the dates (iat,exp, andnbfwhen set); - every claim the issuer did not make selectively disclosable (for Self, for example
identity_levelanddocument_verified).
So two services that compare notes can tell they saw the same person. This is what every presentation carries; it is not a list the wallet shows on its sharing screen.
Next steps
Look at the live services, save a test credential in the devnet Hub, and answer a test request.
Issue a credentialServe OpenID4VCI, bind to the subject's key, publish status, deposit offers.
Request proofBuild a signed request, deposit it, verify the encrypted response.
Hold and share credentialsThe Auth Hub wallet, blocking a sender, and the self-sovereign path for apps with their own keys.
Standards and conformanceEvery specification and version, what is implemented, and the EUDI Wallet comparison.
Credentials API referenceAuthentication, endpoints, limits and error codes of the Credentials worker and the Hub.